50std::vector<std::pair<int, double>>
53 std::vector<std::pair<int, double>>
result;
56 for(
const std::pair<int, double>& bit : bits )
58 if( prevbit != bit.first )
104 status &=
m_file.Init( parser );
118 pin.m_parent = &kComponent;
127 pinA->m_complementaryPin = pinB;
184 if( !std::isnan( aPin.
m_Rpin ) )
186 m_Rpin.value[IBIS_CORNER::TYP] = aPin.m_Rpin;
187 m_Rpin.value[IBIS_CORNER::MIN] = aPin.m_Rpin;
188 m_Rpin.value[IBIS_CORNER::MAX] = aPin.m_Rpin;
191 if( !std::isnan( aPin.
m_Lpin ) )
193 m_Lpin.value[IBIS_CORNER::TYP] = aPin.m_Lpin;
194 m_Lpin.value[IBIS_CORNER::MIN] = aPin.m_Lpin;
195 m_Lpin.value[IBIS_CORNER::MAX] = aPin.m_Lpin;
198 if( !std::isnan( aPin.
m_Cpin ) )
200 m_Cpin.value[IBIS_CORNER::TYP] = aPin.m_Cpin;
201 m_Cpin.value[IBIS_CORNER::MIN] = aPin.m_Cpin;
202 m_Cpin.value[IBIS_CORNER::MAX] = aPin.m_Cpin;
205 bool modelSelected =
false;
206 std::vector<std::string> listOfModels;
210 if( !strcmp( modelSelector.m_name.c_str(), aPin.m_modelName.c_str() ) )
212 for( const IbisModelSelectorEntry& model : modelSelector.m_models )
213 listOfModels.push_back( model.m_modelName );
215 modelSelected = true;
221 listOfModels.push_back( aPin.m_modelName );
223 for(
const std::string& modelName : listOfModels )
225 for( KIBIS_MODEL& model : aModels )
227 if( !strcmp( model.m_name.c_str(), modelName.c_str() ) )
228 m_models.push_back( &model );
387 KIBIS_PIN kPin( aTopLevel, iPin, aSource.m_package, aParser, nullptr,
388 m_topLevel->m_models );
389 status &= kPin.m_valid;
390 m_pins.push_back( kPin );
395 m_seriesPinMappings.push_back( { iPair.m_pin1, iPair.m_pin2, iPair.m_modelName,
396 iPair.m_functionTableGroup } );
410 const std::string* other =
nullptr;
436 if(
pin.m_pinNumber == aPinNumber )
445 std::vector<std::pair<IbisWaveform*, IbisWaveform*>> pairs;
461 pairs.emplace_back( wf1, wf2 );
474 std::string GC_GND =
"GC_GND";
475 std::string PC_PWR =
"PC_PWR";
476 std::string PU_PWR =
"PU_PWR";
477 std::string PD_GND =
"PD_GND";
478 std::string DIE =
"DIE";
479 std::string DIEBUFF =
"DIEBUFF";
484 GC_GND += std::to_string( aIndex );
485 PC_PWR += std::to_string( aIndex );
486 PU_PWR += std::to_string( aIndex );
487 PD_GND += std::to_string( aIndex );
488 DIE += std::to_string( aIndex );
489 DIEBUFF += std::to_string( aIndex );
492 std::string GC =
"GC";
493 std::string PC =
"PC";
494 std::string PU =
"PU";
495 std::string PD =
"PD";
497 GC += std::to_string( aIndex );
498 PC += std::to_string( aIndex );
499 PU += std::to_string( aIndex );
500 PD += std::to_string( aIndex );
503 result +=
"VPWR POWER GND ";
506 result +=
"CCPOMP " + DIE +
" GND ";
512 result +=
m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND,
false, GC, supply );
513 result +=
"Vmeas" + GC +
" GND " + GC_GND +
" 0\n";
519 result +=
"Vmeas" + PC +
" POWER " + PC_PWR +
" 0\n";
524 result +=
m_pulldown.Spice( aIndex * 4 + 3, DIEBUFF, PD_GND,
false, PD, supply );
525 result +=
"VmeasPD GND " + PD_GND +
" 0\n";
526 result +=
"BKD GND " + DIE +
" i=( i(VmeasPD) * v(KD) )\n";
531 result +=
m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIEBUFF,
false, PU, supply );
532 result +=
"VmeasPU POWER " + PU_PWR +
" 0\n";
533 result +=
"BKU POWER " + DIE +
" i=( -i(VmeasPU) * v(KU) )\n";
537 result +=
"BDIEBUFF " + DIEBUFF +
" GND v=v(" + DIE +
")\n";
549 GC_GND =
"GC_GND" + std::to_string( aIndex );
550 PC_PWR =
"PC_PWR" + std::to_string( aIndex );
552 GC =
"GC" + std::to_string( aIndex );
553 PC =
"PC" + std::to_string( aIndex );
555 if( submodel.HasGNDClamp() )
557 result += submodel.m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND,
false, GC, supply );
558 result +=
"Vmeas" + GC +
" GND " + GC_GND +
" 0\n";
561 if( submodel.HasPOWERClamp() )
563 result += submodel.m_POWERClamp.Spice( aIndex * 4 + 2, PC_PWR, DIE,
true, PC, supply );
564 result +=
"Vmeas" + PC +
" POWER " + PC_PWR +
" 0\n";
573 const std::string& aPort1,
const std::string& aPort2,
575 const std::string& aGate )
const
579 std::string idx = std::to_string( aIndex );
583 const bool gated = !aGate.empty();
584 std::string p2 = gated ? (
"ARM_OUT" + idx ) : aPort2;
588 result +=
"R_S" + idx +
" " + aPort1 +
" " + p2 +
" ";
595 std::string nL =
"n_L" + idx;
596 result +=
"L_S" + idx +
" " + aPort1 +
" " + nL +
" ";
601 result +=
"R_Sl" + idx +
" " + nL +
" " + p2 +
" ";
608 std::string node1 = aPort1;
613 std::string n =
"n_Cr" + idx +
"_" + std::to_string( subnode++ );
614 result +=
"R_Sc" + idx +
" " + node1 +
" " + n +
" ";
622 std::string n =
"n_Cl" + idx +
"_" + std::to_string( subnode++ );
623 result +=
"L_Sc" + idx +
" " + node1 +
" " + n +
" ";
629 result +=
"C_S" + idx +
" " + node1 +
" " + p2 +
" ";
638 std::string expr =
"pwl(v(" + aPort1 +
"," + p2 +
")";
642 if( std::isnan( e.
I.
value[corner] ) )
649 result +=
"B_SC" + idx +
" " + aPort1 +
" " + p2 +
" i = " + expr +
"\n";
659 if(
mosfet.m_table.m_entries.empty() || std::isnan(
mosfet.m_Vds ) ||
mosfet.m_Vds <= 0.0 )
662 std::string suffix = idx +
"_" + std::to_string( mIdx++ );
663 std::string tableExpr =
"pwl(" +
doubleToString( vcc ) +
"-min(v(" + aPort1 +
"),v("
668 if( std::isnan( e.
I.
value[corner] ) )
676 result +=
"B_M" + suffix +
" " + aPort1 +
" " + p2 +
" i = ";
677 result +=
"(" + tableExpr +
") * (v(" + aPort1 +
"," + p2 +
") / "
684 result +=
"R_G" + idx +
" " + p2 +
" " + aPort2 +
" R='0.001 / ((" + aGate +
") + 1e-12)'";
713 for(
int i = 0; i < nbPoints; i++ )
718 outEntry.
t = inEntry.
t;
736 return m_pullup.m_entries.size() > 0;
753 const std::vector<std::pair<int, double>>& aBits,
754 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
759 std::vector<int> stimuliIndex;
771 double delta = deltaR + deltaF;
777 for(
const std::pair<int, double>& bit : aBits )
780 double timing = bit.second;
783 if ( bit.first != prevBit )
790 stimuliIndex.push_back( i );
793 simul += std::to_string( i );
795 simul += std::to_string( i );
798 simul +=
" pwl ( \n+";
805 double deltaT = entry1.
t - entry0.
t;
834 for(
int ii: stimuliIndex )
836 simul +=
" v( stimuli";
837 simul += std::to_string( ii );
843 if( ( aBits.size() > 0 ) && ( aBits[0].first == 0 ) )
844 simul +=
doubleToString( aPair.second->m_table.m_entries.at( 0 ).V.value[supply] );
846 simul +=
doubleToString( aPair.first->m_table.m_entries.at( 0 ).V.value[supply] );
858 std::string GC_GND =
"GC_GND";
859 std::string PC_PWR =
"PC_PWR";
860 std::string PU_PWR =
"PU_PWR";
861 std::string PD_GND =
"PD_GND";
862 std::string DIE =
"DIE";
864 GC_GND += std::to_string( aIndex );
865 PC_PWR += std::to_string( aIndex );
866 PU_PWR += std::to_string( aIndex );
867 PD_GND += std::to_string( aIndex );
868 DIE += std::to_string( aIndex );
871 std::string GC =
"GC";
872 std::string PC =
"PC";
873 std::string PU =
"PU";
874 std::string PD =
"PD";
876 GC += std::to_string( aIndex );
877 PC += std::to_string( aIndex );
878 PU += std::to_string( aIndex );
879 PD += std::to_string( aIndex );
882 simul += aModel.
m_GNDClamp.
Spice( aIndex * 4 + 1, DIE, GC_GND,
false, GC, supply );
885 simul += aModel.
m_POWERClamp.
Spice( aIndex * 4 + 2, PC_PWR, DIE,
true, PC, supply );
888 simul += aModel.
m_pulldown.
Spice( aIndex * 4 + 3, DIE, PD_GND,
false, PD, supply );
891 simul += aModel.
m_pullup.
Spice( aIndex * 4 + 4, PU_PWR, DIE,
false, PU, supply );
899 const std::string outputFileName =
m_topLevel->m_cacheDir +
"temp_output.spice";
901 if( std::remove( outputFileName.c_str() ) )
907 throw std::runtime_error(
"Could not create simulator instance" );
910 ng->LoadNetlist( aSimul );
912 std::ifstream KuKdfile;
913 KuKdfile.open( outputFileName );
915 std::vector<double>
ku, kd, t;
920 bool valuesTagFound =
false;
922 while( std::getline( KuKdfile, line ) )
924 if( line.find(
"Values:" ) != std::string::npos )
926 valuesTagFound =
true;
931 if( !valuesTagFound )
937 double t_v, ku_v, kd_v;
943 std::getline( KuKdfile, line );
951 line = line.substr( line.find_first_of(
"\t" ) + 1 );
952 t_v = std::stod( line );
954 case 1: ku_v = std::stod( line );
break;
956 kd_v = std::stod( line );
957 ku.push_back( ku_v );
958 kd.push_back( kd_v );
967 catch(
const std::exception& )
972 std::getline( KuKdfile, line );
979 if( std::remove( outputFileName.c_str() ) )
985 m_Kd = std::move( kd );
986 m_t = std::move( t );
991 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
998 std::string simul =
"";
1000 simul +=
"*THIS IS NOT A VALID SPICE MODEL.\n";
1001 simul +=
"*This part is intended to be executed by Kibis internally.\n";
1002 simul +=
"*You should not be able to read this.\n\n";
1004 simul +=
".SUBCKT DRIVER";
1005 simul += std::to_string( aIndex );
1006 simul +=
" POWER GND PIN \n";
1008 simul +=
"Vdummy 2 PIN 0\n";
1010 if( ( aPair.first->m_R_dut != 0 ) || ( aPair.first->m_L_dut != 0 )
1011 || ( aPair.first->m_C_dut != 0 ) )
1013 Report(
_(
"Kibis does not support DUT values yet. "
1014 "https://ibis.org/summits/nov16a/chen.pdf" ),
1019 simul +=
"CCPOMP 2 GND ";
1031 wave->
Check( risingWF, fallingWF );
1040 simul +=
"Vsig DIE0 GND ";
1048 simul +=
"Vsig DIE0 GND ";
1059 simul +=
addDie( aModel, aParam, 0 );
1061 simul +=
"\n.ENDS DRIVER\n\n";
1067 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
1073 std::string simul =
"";
1081 std::vector<double>
ku, kd, t;
1086 m_Kd = std::move( kd );
1087 m_t = std::move( t );
1091 simul +=
KuKdDriver( aModel, aPair, aParam, 0 );
1092 simul +=
"\n x1 3 0 1 DRIVER0 \n";
1094 simul +=
"VCC 3 0 ";
1098 simul +=
"Lfixture 1 4 ";
1101 simul +=
"Rfixture 4 5 ";
1104 simul +=
"Cfixture 4 0 ";
1107 simul +=
"Vfixture 5 0 ";
1110 simul +=
"VmeasIout x1.DIE0 x1.2 0\n";
1111 simul +=
"VmeasPD 0 x1.PD_GND0 0\n";
1112 simul +=
"VmeasPU x1.PU_PWR0 3 0\n";
1113 simul +=
"VmeasPC x1.PC_PWR0 3 0\n";
1114 simul +=
"VmeasGC 0 x1.GC_GND0 0\n";
1118 Report(
_(
"Model has only one waveform pair, reduced accuracy" ),
1120 simul +=
"Bku KU 0 v=( (i(VmeasIout)-i(VmeasPC)-i(VmeasGC)-i(VmeasPD) "
1121 ")/(i(VmeasPU)-i(VmeasPD)))\n";
1122 simul +=
"Bkd KD 0 v=(1-v(KU))\n";
1127 simul +=
"Bku KD 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPD)))\n";
1128 simul +=
"Bkd KU 0 v=0\n";
1133 simul +=
"Bku KU 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPU)))\n";
1134 simul +=
"Bkd KD 0 v=0\n";
1147 simul +=
".tran 0.1n ";
1156 simul +=
".tran 0.5 1 \n";
1160 simul +=
".control run \n";
1161 simul +=
"set filetype=ascii\n";
1166 std::string outputFileName =
m_topLevel->m_cacheDir +
"temp_output.spice";
1167 simul +=
"write '" + outputFileName +
"' v(KU) v(KD)\n";
1169 simul +=
".endc \n";
1179 std::vector<double>
ku, kd, t;
1195 for(
const std::pair<int, double>& bit : bits )
1197 ku.push_back( bit.first ? 0 : 1 );
1198 kd.push_back( bit.first ? 1 : 0 );
1199 t.push_back( bit.second );
1200 ku.push_back( bit.first ? 1 : 0 );
1201 kd.push_back( bit.first ? 0 : 1 );
1202 t.push_back( bit.second
1213 kd.push_back( wave->
inverted ? 1 : 0 );
1220 kd.push_back( wave->
inverted ? 0 : 1 );
1233 m_Kd = std::move( kd );
1234 m_t = std::move( t );
1239 const std::pair<IbisWaveform*, IbisWaveform*>& aPair1,
1240 const std::pair<IbisWaveform*, IbisWaveform*>& aPair2,
1243 std::string simul =
"";
1253 std::vector<double>
ku, kd, t;
1258 m_Kd = std::move( kd );
1259 m_t = std::move( t );
1263 simul +=
KuKdDriver( aModel, aPair1, aParam, 0 );
1264 simul +=
KuKdDriver( aModel, aPair2, aParam, 1 );
1265 simul +=
"\n x1 3 0 1 DRIVER0 \n";
1267 simul +=
"VCC 3 0 ";
1271 simul +=
"Lfixture0 1 4 ";
1274 simul +=
"Rfixture0 4 5 ";
1277 simul +=
"Cfixture0 4 0 ";
1280 simul +=
"Vfixture0 5 0 ";
1283 simul +=
"VmeasIout0 x1.2 x1.DIE0 0\n";
1284 simul +=
"VmeasPD0 0 x1.PD_GND0 0\n";
1285 simul +=
"VmeasPU0 x1.PU_PWR0 3 0\n";
1286 simul +=
"VmeasPC0 x1.PC_PWR0 3 0\n";
1287 simul +=
"VmeasGC0 0 x1.GC_GND0 0\n";
1290 simul +=
"\n x2 3 0 7 DRIVER1 \n";
1292 simul +=
"Lfixture1 7 8 ";
1295 simul +=
"Rfixture1 8 9 ";
1298 simul +=
"Cfixture1 8 0 ";
1301 simul +=
"Vfixture1 9 0 ";
1304 simul +=
"VmeasIout1 x2.2 x2.DIE0 0\n";
1305 simul +=
"VmeasPD1 0 x2.PD_GND0 0\n";
1306 simul +=
"VmeasPU1 x2.PU_PWR0 3 0\n";
1307 simul +=
"VmeasPC1 x2.PC_PWR0 3 0\n";
1308 simul +=
"VmeasGC1 0 x2.GC_GND0 0\n";
1313 "Bku KU 0 v=( ( i(VmeasPD1) * ( i(VmeasIout0) + i(VmeasPC0) + i(VmeasGC0) ) - "
1314 "i(VmeasPD0) * ( i(VmeasIout1) + i(VmeasPC1) + i(VmeasGC1) ) )/ ( i(VmeasPU1) "
1316 "i(VmeasPD0) - i(VmeasPU0) * i(VmeasPD1) ) )\n";
1318 "Bkd KD 0 v=( ( i(VmeasPU1) * ( i(VmeasIout0) + i(VmeasPC0) + i(VmeasGC0) ) - "
1319 "i(VmeasPU0) * ( i(VmeasIout1) + i(VmeasPC1) + i(VmeasGC1) ) )/ ( i(VmeasPD1) "
1321 "i(VmeasPU0) - i(VmeasPD0) * i(VmeasPU1) ) )\n";
1327 Report(
_(
"There are two waveform pairs, but only one transistor. More equations than "
1330 simul +=
"Bku KD 0 v=( ( i(VmeasIout0)+i(VmeasPC0)+i(VmeasGC0) )/(i(VmeasPD0)))\n";
1331 simul +=
"Bkd KU 0 v=0\n";
1336 Report(
_(
"There are two waveform pairs, but only one transistor. More equations than "
1339 simul +=
"Bku KU 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPU)))\n";
1340 simul +=
"Bkd KD 0 v=0\n";
1353 simul +=
".tran 0.1n ";
1362 simul +=
".tran 0.5 1 \n";
1366 simul +=
".control run \n";
1367 simul +=
"set filetype=ascii\n";
1369 simul +=
"plot v(KU) v(KD)\n";
1371 std::string outputFileName =
m_topLevel->m_cacheDir +
"temp_output.spice";
1372 simul +=
"write '" + outputFileName +
"' v(KU) v(KD)\n";
1374 simul +=
".endc \n";
1405 result =
"\n*Driver model generated by Kicad using Ibis data. ";
1407 result +=
"\n*Pin number: ";
1409 result +=
"\n*Signal name: ";
1421 result +=
"LPIN DIE0 1 ";
1424 result +=
"CPIN PIN GND ";
1428 std::vector<std::pair<IbisWaveform*, IbisWaveform*>> wfPairs = aModel.
waveformPairs();
1435 Report(
_(
"Model has no waveform pair, using [Ramp] instead, poor accuracy" ),
1449 Report(
_(
"Model has more than 2 waveform pairs, using the first two." ),
1456 result +=
"Vku KU GND pwl ( ";
1458 for(
size_t i = 0; i <
m_t.size(); i++ )
1469 result +=
"Vkd KD GND pwl ( ";
1471 for(
size_t i = 0; i <
m_t.size(); i++ )
1483 result +=
"\n.ENDS DRIVER\n\n";
1492 Report(
_(
"Series and Series_switch models are passive devices, not drivers." ),
1524 result =
"*Device model generated by Kicad using Ibis data.";
1533 result +=
"LPIN DIE0 1 ";
1536 result +=
"CPIN PIN GND ";
1542 result +=
"\n.ENDS DEVICE\n\n";
1544 aDest = std::move(
result );
1554 Report(
_(
"Series model has no [Series Pin Mapping] partner pin." ),
1560 std::string
result =
"\n*Series device model generated by KiCad using IBIS data.\n";
1565 result +=
" PIN_A PIN_B\n";
1568 result +=
".param SW_STATE=1\n";
1570 auto emitPinParasitics = [&](
const std::string& aSuffix,
const KIBIS_PIN& aPin,
1571 const std::string& aPin_ext,
const std::string& aDie )
1573 std::string n1 =
"n_pin" + aSuffix;
1574 result +=
"RPIN" + aSuffix +
" " + n1 +
" " + aPin_ext +
" ";
1577 result +=
"LPIN" + aSuffix +
" " + aDie +
" " + n1 +
" ";
1580 result +=
"CPIN" + aSuffix +
" " + aPin_ext +
" 0 ";
1585 emitPinParasitics(
"A", *
this,
"PIN_A",
"DIE_A" );
1586 emitPinParasitics(
"B", *
partner,
"PIN_B",
"DIE_B" );
1600 result +=
"\n.ENDS DEVICE\n\n";
1602 aDest = std::move(
result );
1624 result =
"\n*Differential driver model generated by Kicad using Ibis data. ";
1628 result +=
" GND PIN_P PIN_N\n";
1638 result +=
"x1 GND PIN_P " + aName +
"_P \n";
1639 result +=
"x2 GND PIN_N " + aName +
"_N \n";
1642 result +=
"\n.ENDS " + aName +
"\n\n";
1657 result =
"\n*Differential device model generated by Kicad using Ibis data. ";
1661 result +=
" GND PIN_P PIN_N\n";
1668 result +=
"x1 GND PIN_P " + aName +
"_P \n";
1669 result +=
"x2 GND PIN_N " + aName +
"_N \n";
1672 result +=
"\n.ENDS " + aName +
"\n\n";
1685 if(
model.m_name == aName )
1697 if( cmp.m_name == aName )
1707 if( aString ==
"MIN" )
1709 else if( aString ==
"MAX" )
1718 std::vector<std::pair<int, double>> bits;
1719 std::pair<int, double> bit;
1728 std::vector<std::pair<int, double>> bits;
1729 std::pair<int, double> bit;
1737 std::vector<std::pair<int, double>> bits;
1743 std::vector<std::pair<int, double>> bits;
1745 for(
int i = 0; i <
m_cycles; i++ )
1747 std::pair<int, double> bit;
1750 bits.push_back( bit );
1754 bits.push_back( bit );
1763 std::vector<std::pair<int, double>> bitSequence;
1764 uint8_t polynomial = 0b1100000;
1768 uint8_t
seed = 0x12;
1769 uint8_t lfsr =
seed;
1783 uint8_t lsb = lfsr & 0x01;
1784 bitSequence.emplace_back( (
static_cast<uint8_t
>(
inverted ) ^ lsb ? 1 : 0 ), t );
1792 }
while ( ++bits <
m_bits );
1838 status &= aRisingWf && aFallingWf;
1936 if(
m_bitrate && aRisingWf && aFallingWf
void Report(const std::string &aMsg, SEVERITY aSeverity=RPT_SEVERITY_INFO) const
Print a message.
IBIS_BASE(REPORTER *aReporter)
static std::string doubleToString(double aNumber)
Convert a double to string using scientific notation.
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
One row of a [Series Pin Mapping] table (IBIS 4.1+).
std::string m_manufacturer
std::vector< IbisComponentPin > m_pins
std::vector< IbisComponentSeriesPinMapping > m_seriesPinMappings
std::vector< IbisDiffPinEntry > m_entries
std::vector< IbisComponent > m_components
std::map< std::string, IbisSubmodel > m_submodels
std::vector< IbisModel > m_models
std::vector< IbisModelSelector > m_modelSelectors
std::string m_modelDescription
std::vector< IbisModelSelectorEntry > m_models
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
std::vector< IbisSubmodelMode > m_submodels
std::vector< IbisWaveform * > m_risingWaveforms
TypMinMaxValue m_POWERClampReference
IbisSeriesData m_seriesOn
IBIS_MODEL_POLARITY m_polarity
IBIS_MODEL_ENABLE m_enable
TypMinMaxValue m_temperatureRange
std::vector< IbisWaveform * > m_fallingWaveforms
TypMinMaxValue m_pulldownReference
TypMinMaxValue m_GNDClampReference
TypMinMaxValue m_voltageRange
bool ParseFile(const std::string &aFileName)
Parse a file.
TypMinMaxValue m_RlSeries
TypMinMaxValue m_LcSeries
std::vector< IbisMosfetEntry > m_seriesMosfet
TypMinMaxValue m_RcSeries
IBIS_SUBMODEL_MODE m_mode
TypMinMaxValue m_VtriggerR
IBIS_SUBMODEL_TYPE m_type
TypMinMaxValue m_VtriggerF
KIBIS_BASE(KIBIS *aTopLevel)
KIBIS_COMPONENT(KIBIS &aToplevel, const IbisComponent &aSource, IbisParser &aParser)
std::vector< KIBIS_PIN > m_pins
std::string m_manufacturer
Name of the manufacturer.
std::string m_name
Name of the component.
KIBIS_PIN * GetPin(const std::string &aPinNumber)
Get a pin by its number ( 1, 2, A1, A2, ... )
KIBIS_FILE(KIBIS &aTopLevel)
bool Init(const IbisParser &aParser)
std::vector< IbisWaveform * > m_fallingWaveforms
IbisWaveform TrimWaveform(const IbisWaveform &aIn) const
Copy a waveform, and substract the first value to all samples.
IBIS_MODEL_ENABLE m_enable
bool HasPOWERClamp() const
Return true if the model has a clamp diode to the power net.
std::vector< IbisWaveform * > m_risingWaveforms
bool HasPullup() const
Return true if the model has a pullup transistor.
bool HasGNDClamp() const
Return true if the model has a clamp diode to the gnd net.
std::string SpiceDie(const KIBIS_PARAMETER &aParam, int aIndex, bool aDriver) const
Generate the spice directive to simulate the die.
IbisSeriesData m_seriesOn
TypMinMaxValue m_pulldownReference
TypMinMaxValue m_GNDClampReference
bool HasPulldown() const
Return true if the model has a pulldown transistor.
std::vector< KIBIS_SUBMODEL > m_submodels
IBIS_MODEL_POLARITY m_polarity
std::string generateSquareWave(const std::string &aNode1, const std::string &aNode2, const std::vector< std::pair< int, double > > &aBits, const std::pair< IbisWaveform *, IbisWaveform * > &aPair, const KIBIS_PARAMETER &aParam)
Generate a square waveform.
TypMinMaxValue m_temperatureRange
TypMinMaxValue m_voltageRange
std::string m_description
KIBIS_MODEL(KIBIS &aTopLevel, const IbisModel &aSource, IbisParser &aParser)
TypMinMaxValue m_pullupReference
std::vector< std::pair< IbisWaveform *, IbisWaveform * > > waveformPairs()
Create waveform pairs.
TypMinMaxValue m_POWERClampReference
std::string SpiceSeriesDie(const KIBIS_PARAMETER &aParam, int aIndex, const std::string &aPort1, const std::string &aPort2, const IbisSeriesData &aData, const std::string &aGate) const
Emit the two-port Series die.
IbisSeriesData m_seriesOff
KIBIS_ACCURACY m_accuracy
void SetCornerFromString(IBIS_CORNER &aCorner, const std::string &aString)
KIBIS_WAVEFORM * m_waveform
TypMinMaxValue m_Rpin
Resistance from die to pin.
bool writeSpiceDiffDriver(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
TypMinMaxValue m_Lpin
Inductance from die to pin.
void getKuKdFromFile(const std::string &aSimul)
Update m_Ku, m_Kd using with two waveform inputs.
KIBIS_COMPONENT * m_parent
std::vector< double > m_Ku
std::string m_pinNumber
Pin Number Examples : 1, 2, 3 ( or for BGA ), A1, A2, A3, etc...
std::string addDie(KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam, int aIndex)
Generate the spice directive to simulate the die for Ku/Kd estimation.
bool writeSpiceDevice(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
std::vector< double > m_t
TypMinMaxValue m_Cpin
Capacitance from pin to GND.
std::string m_signalName
Name of the pin Examples : "VCC", "GPIOA", "CLK", etc...
void getKuKdTwoWaveforms(KIBIS_MODEL &aModel, const std::pair< IbisWaveform *, IbisWaveform * > &aPair1, const std::pair< IbisWaveform *, IbisWaveform * > &aPair2, const KIBIS_PARAMETER &aParam)
Update m_Ku, m_Kd using with two waveform inputs.
void getKuKdOneWaveform(KIBIS_MODEL &aModel, const std::pair< IbisWaveform *, IbisWaveform * > &aPair, const KIBIS_PARAMETER &aParam)
Update m_Ku, m_Kd using with a single waveform input.
bool writeSpiceDiffDevice(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
std::string KuKdDriver(KIBIS_MODEL &aModel, const std::pair< IbisWaveform *, IbisWaveform * > &aPair, const KIBIS_PARAMETER &aParam, int aIndex)
Update m_Ku, m_Kd using with two waveform inputs.
KIBIS_PIN(KIBIS &aTopLevel, const IbisComponentPin &aPin, const IbisComponentPackage &aPackage, IbisParser &aParser, KIBIS_COMPONENT *aParent, std::vector< KIBIS_MODEL > &aModels)
KIBIS_PIN * SeriesPartner(std::string *aModelName=nullptr, std::string *aGroupName=nullptr) const
Partner pin from [Series Pin Mapping], or nullptr.
std::vector< double > m_Kd
bool writeSpiceDriver(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
KIBIS_PIN * m_complementaryPin
void getKuKdNoWaveform(KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Update m_Ku, m_Kd using no falling / rising waveform inputs ( low accuracy )
KIBIS_SUBMODEL(KIBIS &aTopLevel, const IbisSubmodel &aSource, IBIS_SUBMODEL_MODE aMode)
bool HasPOWERClamp() const
Return true if the model has a clamp diode to the power net.
IBIS_SUBMODEL_MODE m_mode
bool HasGNDClamp() const
Return true if the model has a clamp diode to the gnd net.
IBIS_SUBMODEL_TYPE m_type
std::vector< KIBIS_MODEL > m_models
KIBIS()
Constructor for unitialized KIBIS members.
std::vector< KIBIS_COMPONENT > m_components
KIBIS_MODEL * GetModel(const std::string &aName)
Return the model with name aName .
KIBIS_COMPONENT * GetComponent(const std::string &aName)
Return the component with name aName .
A pure virtual class used to derive REPORTER objects from.
static std::shared_ptr< SPICE_SIMULATOR > CreateInstance(const std::string &aName)
std::vector< VTtableEntry > m_entries
std::vector< std::pair< int, double > > SimplifyBitSequence(const std::vector< std::pair< int, double > > &bits)
IBIS_CORNER ReverseLogic(IBIS_CORNER aIn)
KIBIS_ACCURACY
Accuracy level.
const IbisMosfetEntry & mosfet
wxString result
Test unit parsing edge cases and error handling.