KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kibis.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 Fabien Corona f.corona<at>laposte.net
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
18 * to endorse or promote products derived from this software without specific
19 * prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
33#include "kibis.h"
34#include "ibis_parser.h"
35#include <sstream>
36#include <sim/spice_simulator.h>
37
38
39// _() is used here to mark translatable strings in IBIS_REPORTER::Report()
40// However, currently non ASCII7 chars are nor correctly handled when printing messages
41// So we disable translations
42#if 0
43#include <wx/intl.h> // for _() macro and wxGetTranslation()
44#else
45#undef _
46#define _( x ) x
47#endif
48
49
50std::vector<std::pair<int, double>>
51SimplifyBitSequence( const std::vector<std::pair<int, double>>& bits )
52{
53 std::vector<std::pair<int, double>> result;
54 int prevbit = -1;
55
56 for( const std::pair<int, double>& bit : bits )
57 {
58 if( prevbit != bit.first )
59 result.push_back( bit );
60
61 prevbit = bit.first;
62 }
63
64 return result;
65}
66
67
69 KIBIS_BASE( aTopLevel, aTopLevel->m_Reporter )
70{
71}
72
73
74KIBIS_BASE::KIBIS_BASE( KIBIS* aTopLevel, REPORTER* aReporter ) :
75 IBIS_BASE( aReporter ),
76 m_topLevel( aTopLevel ),
77 m_valid( false )
78{
79}
80
81
83{
85
86 if( aIn == IBIS_CORNER::MIN )
87 out = IBIS_CORNER::MAX;
88 else if( aIn == IBIS_CORNER::MAX )
89 out = IBIS_CORNER::MIN;
90
91 return out;
92}
93
94KIBIS::KIBIS( const std::string& aFileName, REPORTER* aReporter ) :
95 KIBIS_BASE( this, aReporter ),
96 m_file( *this )
97{
98 IbisParser parser( m_Reporter );
99 bool status = true;
100
101 parser.m_parrot = false;
102 status &= parser.ParseFile( aFileName );
103
104 status &= m_file.Init( parser );
105
106 for( const IbisModel& iModel : parser.m_ibisFile.m_models )
107 {
108 KIBIS_MODEL& kModel = m_models.emplace_back( *this, iModel, parser );
109 status &= kModel.m_valid;
110 }
111
112 for( const IbisComponent& iComponent : parser.m_ibisFile.m_components )
113 {
114 KIBIS_COMPONENT& kComponent = m_components.emplace_back( *this, iComponent, parser );
115 status &= kComponent.m_valid;
116
117 for( KIBIS_PIN& pin : kComponent.m_pins )
118 pin.m_parent = &kComponent;
119
120 for( const IbisDiffPinEntry& dpEntry : iComponent.m_diffPin.m_entries )
121 {
122 KIBIS_PIN* pinA = kComponent.GetPin( dpEntry.pinA );
123 KIBIS_PIN* pinB = kComponent.GetPin( dpEntry.pinB );
124
125 if( pinA && pinB )
126 {
127 pinA->m_complementaryPin = pinB;
128 pinB->m_complementaryPin = pinA;
129 }
130 }
131 }
132
133 m_valid = status;
134}
135
136
138 KIBIS_BASE( &aTopLevel )
139{
140 m_fileRev = -1;
141 m_ibisVersion = -1;
142}
143
144
145bool KIBIS_FILE::Init( const IbisParser& aParser )
146{
147 bool status = true;
155
156 m_valid = status;
157
158 return status;
159}
160
161
163 const IbisComponentPackage& aPackage, IbisParser& aParser,
164 KIBIS_COMPONENT* aParent, std::vector<KIBIS_MODEL>& aModels ) :
165 KIBIS_BASE( &aTopLevel ),
166 m_Rpin( aTopLevel.m_Reporter ),
167 m_Lpin( aTopLevel.m_Reporter ),
168 m_Cpin( aTopLevel.m_Reporter )
169{
171 m_pinNumber = aPin.m_pinName;
172 m_parent = aParent;
173
174 m_Rpin = aPackage.m_Rpkg;
175 m_Lpin = aPackage.m_Lpkg;
176 m_Cpin = aPackage.m_Cpkg;
177
178 // The values listed in the [Pin] description section override the default
179 // values defined in [Package]
180
181 // @TODO : Reading the IBIS standard, I can't figure out if we are supposed
182 // to replace typ, min, and max, or just the typ ?
183
184 if( !std::isnan( aPin.m_Rpin ) )
185 {
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;
189 }
190
191 if( !std::isnan( aPin.m_Lpin ) )
192 {
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;
196 }
197
198 if( !std::isnan( aPin.m_Cpin ) )
199 {
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;
203 }
204
205 bool modelSelected = false;
206 std::vector<std::string> listOfModels;
207
208 for( const IbisModelSelector& modelSelector : aParser.m_ibisFile.m_modelSelectors )
209 {
210 if( !strcmp( modelSelector.m_name.c_str(), aPin.m_modelName.c_str() ) )
211 {
212 for( const IbisModelSelectorEntry& model : modelSelector.m_models )
213 listOfModels.push_back( model.m_modelName );
214
215 modelSelected = true;
216 break;
217 }
218 }
219
220 if( !modelSelected )
221 listOfModels.push_back( aPin.m_modelName );
222
223 for( const std::string& modelName : listOfModels )
224 {
225 for( KIBIS_MODEL& model : aModels )
226 {
227 if( !strcmp( model.m_name.c_str(), modelName.c_str() ) )
228 m_models.push_back( &model );
229 }
230 }
231
232 m_valid = true;
233}
234
235
236KIBIS_MODEL::KIBIS_MODEL( KIBIS& aTopLevel, const IbisModel& aSource, IbisParser& aParser ) :
237 KIBIS_BASE( &aTopLevel ),
238 m_C_comp( aTopLevel.m_Reporter ),
239 m_voltageRange( aTopLevel.m_Reporter ),
240 m_temperatureRange( aTopLevel.m_Reporter ),
241 m_pullupReference( aTopLevel.m_Reporter ),
242 m_pulldownReference( aTopLevel.m_Reporter ),
243 m_GNDClampReference( aTopLevel.m_Reporter ),
244 m_POWERClampReference( aTopLevel.m_Reporter ),
245 m_Rgnd( aTopLevel.m_Reporter ),
246 m_Rpower( aTopLevel.m_Reporter ),
247 m_Rac( aTopLevel.m_Reporter ),
248 m_Cac( aTopLevel.m_Reporter ),
249 m_GNDClamp( aTopLevel.m_Reporter ),
250 m_POWERClamp( aTopLevel.m_Reporter ),
251 m_pullup( aTopLevel.m_Reporter ),
252 m_pulldown( aTopLevel.m_Reporter ),
253 m_ramp( aTopLevel.m_Reporter )
254{
255 bool status = true;
256
257 m_name = aSource.m_name;
258 m_type = aSource.m_type;
259
260 m_description = std::string( "No description available." );
261
262 for( const IbisModelSelector& modelSelector : aParser.m_ibisFile.m_modelSelectors )
263 {
264 for( const IbisModelSelectorEntry& entry : modelSelector.m_models )
265 {
266 if( !strcmp( entry.m_modelName.c_str(), m_name.c_str() ) )
268 }
269 }
270
271 m_vinh = aSource.m_vinh;
272 m_vinl = aSource.m_vinl;
273 m_vref = aSource.m_vref;
274 m_rref = aSource.m_rref;
275 m_cref = aSource.m_cref;
276 m_vmeas = aSource.m_vmeas;
277
278 m_enable = aSource.m_enable;
279 m_polarity = aSource.m_polarity;
280
281 m_ramp = aSource.m_ramp;
284 m_GNDClamp = aSource.m_GNDClamp;
286 m_POWERClamp = aSource.m_POWERClamp;
288
289 m_C_comp = aSource.m_C_comp;
294
295 m_Rgnd = aSource.m_Rgnd;
296 m_Rpower = aSource.m_Rpower;
297 m_Rac = aSource.m_Rac;
298 m_Cac = aSource.m_Cac;
299 m_pullup = aSource.m_pullup;
300 m_pulldown = aSource.m_pulldown;
301
302 m_valid = status;
303}
304
305
307 IbisParser& aParser ) :
308 KIBIS_BASE( &aTopLevel )
309{
310 bool status = true;
311
312 m_name = aSource.m_name;
314
315 for( const IbisComponentPin& iPin : aSource.m_pins )
316 {
317 if( iPin.m_dummy )
318 continue;
319
320 KIBIS_PIN kPin( aTopLevel, iPin, aSource.m_package, aParser, nullptr,
322 status &= kPin.m_valid;
323 m_pins.push_back( kPin );
324 }
325
326 m_valid = status;
327}
328
329
330KIBIS_PIN* KIBIS_COMPONENT::GetPin( const std::string& aPinNumber )
331{
332 for( KIBIS_PIN& pin : m_pins )
333 {
334 if( pin.m_pinNumber == aPinNumber )
335 return &pin;
336 }
337
338 return nullptr;
339}
340
341std::vector<std::pair<IbisWaveform*, IbisWaveform*>> KIBIS_MODEL::waveformPairs()
342{
343 std::vector<std::pair<IbisWaveform*, IbisWaveform*>> pairs;
344 IbisWaveform* wf1;
345 IbisWaveform* wf2;
346
347 for( size_t i = 0; i < m_risingWaveforms.size(); i++ )
348 {
349 for( size_t j = 0; j < m_fallingWaveforms.size(); j++ )
350 {
351 wf1 = m_risingWaveforms.at( i );
352 wf2 = m_fallingWaveforms.at( j );
353
354 if( wf1->m_R_fixture == wf2->m_R_fixture && wf1->m_L_fixture == wf2->m_L_fixture
355 && wf1->m_C_fixture == wf2->m_C_fixture && wf1->m_V_fixture == wf2->m_V_fixture
356 && wf1->m_V_fixture_min == wf2->m_V_fixture_min
357 && wf1->m_V_fixture_max == wf2->m_V_fixture_max )
358 {
359 pairs.emplace_back( wf1, wf2 );
360 }
361 }
362 }
363
364 return pairs;
365}
366
367
368std::string KIBIS_MODEL::SpiceDie( const KIBIS_PARAMETER& aParam, int aIndex ) const
369{
370 std::string result;
371
372 std::string GC_GND = "GC_GND";
373 std::string PC_PWR = "PC_PWR";
374 std::string PU_PWR = "PU_PWR";
375 std::string PD_GND = "PD_GND";
376 std::string DIE = "DIE";
377 std::string DIEBUFF = "DIEBUFF";
378
379 IBIS_CORNER supply = aParam.m_supply;
380 IBIS_CORNER ccomp = aParam.m_Ccomp;
381
382 GC_GND += std::to_string( aIndex );
383 PC_PWR += std::to_string( aIndex );
384 PU_PWR += std::to_string( aIndex );
385 PD_GND += std::to_string( aIndex );
386 DIE += std::to_string( aIndex );
387 DIEBUFF += std::to_string( aIndex );
388
389
390 std::string GC = "GC";
391 std::string PC = "PC";
392 std::string PU = "PU";
393 std::string PD = "PD";
394
395 GC += std::to_string( aIndex );
396 PC += std::to_string( aIndex );
397 PU += std::to_string( aIndex );
398 PD += std::to_string( aIndex );
399
400 result = "\n";
401 result += "VPWR POWER GND ";
402 result += doubleToString( m_voltageRange.value[supply] );
403 result += "\n";
404 result += "CCPOMP " + DIE + " GND ";
405 result += doubleToString( m_C_comp.value[ccomp] );
406 result += "\n";
407
408 if( HasGNDClamp() )
409 {
410 result += m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND, GC, supply );
411 result += "VmeasGC GND " + GC_GND + " 0\n";
412 }
413
414 if( HasPOWERClamp() )
415 {
416 result += m_POWERClamp.Spice( aIndex * 4 + 2, "POWER", DIE, PC, supply );
417 result += "VmeasPC POWER " + PC_PWR + " 0\n";
418 }
419
420 if( HasPulldown() )
421 {
422 result += m_pulldown.Spice( aIndex * 4 + 3, DIEBUFF, PD_GND, PD, supply );
423 result += "VmeasPD GND " + PD_GND + " 0\n";
424 result += "BKD GND " + DIE + " i=( i(VmeasPD) * v(KD) )\n";
425 }
426
427 if( HasPullup() )
428 {
429 result += m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIEBUFF, PU, supply );
430 result += "VmeasPU POWER " + PU_PWR + " 0\n";
431 result += "BKU POWER " + DIE + " i=( -i(VmeasPU) * v(KU) )\n";
432 }
433
434 if ( HasPullup() || HasPulldown() )
435 result += "BDIEBUFF " + DIEBUFF + " GND v=v(" + DIE + ")\n";
436
437 return result;
438}
439
440
442{
443 IbisWaveform out( aIn.m_Reporter );
444
445 const int nbPoints = aIn.m_table.m_entries.size();
446
447 if( nbPoints < 2 )
448 {
449 Report( _( "waveform has less than two points" ), RPT_SEVERITY_ERROR );
450 return out;
451 }
452
453 const double DCtyp = aIn.m_table.m_entries[0].V.value[IBIS_CORNER::TYP];
454 const double DCmin = aIn.m_table.m_entries[0].V.value[IBIS_CORNER::MIN];
455 const double DCmax = aIn.m_table.m_entries[0].V.value[IBIS_CORNER::MAX];
456
457 if( nbPoints == 2 )
458 return out;
459
460 out.m_table.m_entries.clear();
461
462 for( int i = 0; i < nbPoints; i++ )
463 {
464 const VTtableEntry& inEntry = aIn.m_table.m_entries.at( i );
465 VTtableEntry& outEntry = out.m_table.m_entries.emplace_back( out.m_Reporter );
466
467 outEntry.t = inEntry.t;
468 outEntry.V.value[IBIS_CORNER::TYP] = inEntry.V.value[IBIS_CORNER::TYP] - DCtyp;
469 outEntry.V.value[IBIS_CORNER::MIN] = inEntry.V.value[IBIS_CORNER::MIN] - DCmin;
470 outEntry.V.value[IBIS_CORNER::MAX] = inEntry.V.value[IBIS_CORNER::MAX] - DCmax;
471 }
472
473 return out;
474}
475
476
478{
479 return m_pulldown.m_entries.size() > 0;
480}
481
482
484{
485 return m_pullup.m_entries.size() > 0;
486}
487
488
490{
491 return m_GNDClamp.m_entries.size() > 0;
492}
493
494
496{
497 return m_POWERClamp.m_entries.size() > 0;
498}
499
500
501std::string KIBIS_MODEL::generateSquareWave( const std::string& aNode1, const std::string& aNode2,
502 const std::vector<std::pair<int, double>>& aBits,
503 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
504 const KIBIS_PARAMETER& aParam )
505{
506 const IBIS_CORNER supply = aParam.m_supply;
507 std::string simul;
508 std::vector<int> stimuliIndex;
509
510 IbisWaveform risingWF = TrimWaveform( *( aPair.first ) );
511 IbisWaveform fallingWF = TrimWaveform( *( aPair.second ) );
512
513 double deltaR = risingWF.m_table.m_entries.back().V.value[supply]
514 - risingWF.m_table.m_entries.at( 0 ).V.value[supply];
515 double deltaF = fallingWF.m_table.m_entries.back().V.value[supply]
516 - fallingWF.m_table.m_entries.at( 0 ).V.value[supply];
517
518 // Ideally, delta should be equal to zero.
519 // It can be different from zero if the falling waveform does not start were the rising one ended.
520 double delta = deltaR + deltaF;
521
522 int i = 0;
523
524 int prevBit = 2;
525
526 for( const std::pair<int, double>& bit : aBits )
527 {
529 double timing = bit.second;
530
531
532 if ( bit.first != prevBit )
533 {
534 if( bit.first == 1 )
535 WF = &risingWF;
536 else
537 WF = &fallingWF;
538
539 stimuliIndex.push_back( i );
540
541 simul += "Vstimuli";
542 simul += std::to_string( i );
543 simul += " stimuli";
544 simul += std::to_string( i );
545 simul += " ";
546 simul += aNode2;
547 simul += " pwl ( \n+";
548
549 if( i != 0 )
550 {
551 simul += "0 0 ";
552 VTtableEntry entry0 = WF->m_table.m_entries.at( 0 );
553 VTtableEntry entry1 = WF->m_table.m_entries.at( 1 );
554 double deltaT = entry1.t - entry0.t;
555
556 simul += doubleToString( entry0.t + timing - deltaT );
557 simul += " ";
558 simul += "0";
559 simul += "\n+";
560 }
561
562 for( const VTtableEntry& entry : WF->m_table.m_entries )
563 {
564 simul += doubleToString( entry.t + timing );
565 simul += " ";
566 simul += doubleToString( entry.V.value[supply] - delta );
567 simul += "\n+";
568 }
569
570 simul += ")\n";
571 }
572
573 i++;
574 prevBit = bit.first;
575 }
576
577 simul += "bin ";
578 simul += aNode1;
579 simul += " ";
580 simul += aNode2;
581 simul += " v=(";
582
583 for( int ii: stimuliIndex )
584 {
585 simul += " v( stimuli";
586 simul += std::to_string( ii );
587 simul += " ) +\n+";
588 }
589
590 // Depending on the first bit, we add a different DC value
591 // The DC value we add is the first value of the first bit.
592 if( ( aBits.size() > 0 ) && ( aBits[0].first == 0 ) )
593 simul += doubleToString( aPair.second->m_table.m_entries.at( 0 ).V.value[supply] );
594 else
595 simul += doubleToString( aPair.first->m_table.m_entries.at( 0 ).V.value[supply] );
596
597 simul += ")\n";
598 return simul;
599}
600
601
602std::string KIBIS_PIN::addDie( KIBIS_MODEL& aModel, const KIBIS_PARAMETER& aParam, int aIndex )
603{
604 const IBIS_CORNER supply = aParam.m_supply;
605 std::string simul;
606
607 std::string GC_GND = "GC_GND";
608 std::string PC_PWR = "PC_PWR";
609 std::string PU_PWR = "PU_PWR";
610 std::string PD_GND = "PD_GND";
611 std::string DIE = "DIE";
612
613 GC_GND += std::to_string( aIndex );
614 PC_PWR += std::to_string( aIndex );
615 PU_PWR += std::to_string( aIndex );
616 PD_GND += std::to_string( aIndex );
617 DIE += std::to_string( aIndex );
618
619
620 std::string GC = "GC";
621 std::string PC = "PC";
622 std::string PU = "PU";
623 std::string PD = "PD";
624
625 GC += std::to_string( aIndex );
626 PC += std::to_string( aIndex );
627 PU += std::to_string( aIndex );
628 PD += std::to_string( aIndex );
629
630 if( aModel.HasGNDClamp() )
631 simul += aModel.m_GNDClamp.Spice( aIndex * 4 + 1, DIE, GC_GND, GC, supply );
632
633 if( aModel.HasPOWERClamp() )
634 simul += aModel.m_POWERClamp.Spice( aIndex * 4 + 2, PC_PWR, DIE, PC, supply );
635
636 if( aModel.HasPulldown() )
637 simul += aModel.m_pulldown.Spice( aIndex * 4 + 3, DIE, PD_GND, PD, supply );
638
639 if( aModel.HasPullup() )
640 simul += aModel.m_pullup.Spice( aIndex * 4 + 4, PU_PWR, DIE, PU, supply );
641
642 return simul;
643}
644
645
646void KIBIS_PIN::getKuKdFromFile( const std::string& aSimul )
647{
648 const std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
649
650 if( std::remove( outputFileName.c_str() ) )
651 Report( _( "Cannot remove temporary output file" ), RPT_SEVERITY_WARNING );
652
653 std::shared_ptr<SPICE_SIMULATOR> ng = SIMULATOR::CreateInstance( "ng-kibis" );
654
655 if( !ng )
656 throw std::runtime_error( "Could not create simulator instance" );
657
658 ng->Init();
659 ng->LoadNetlist( aSimul );
660
661 std::ifstream KuKdfile;
662 KuKdfile.open( outputFileName );
663
664 std::vector<double> ku, kd, t;
665
666 if( KuKdfile )
667 {
668 std::string line;
669 bool valuesTagFound = false;
670
671 while( std::getline( KuKdfile, line ) ) // skip ngspice output header
672 {
673 if( line.find( "Values:" ) != std::string::npos )
674 {
675 valuesTagFound = true;
676 break;
677 }
678 }
679
680 if( !valuesTagFound )
681 {
682 Report( _( "Missing 'Values:' tag in temporary file" ), RPT_SEVERITY_ERROR );
683 }
684
685 int i = 0;
686 double t_v, ku_v, kd_v;
687
688 try
689 {
690 while( KuKdfile )
691 {
692 std::getline( KuKdfile, line );
693
694 if( line.empty() )
695 continue;
696
697 switch( i )
698 {
699 case 0:
700 line = line.substr( line.find_first_of( "\t" ) + 1 );
701 t_v = std::stod( line );
702 break;
703 case 1: ku_v = std::stod( line ); break;
704 case 2:
705 kd_v = std::stod( line );
706 ku.push_back( ku_v );
707 kd.push_back( kd_v );
708 t.push_back( t_v );
709 break;
710 default: Report( _( "Error while reading temporary file" ), RPT_SEVERITY_ERROR );
711 }
712
713 i = ( i + 1 ) % 3;
714 }
715 }
716 catch( const std::exception& )
717 {
718 Report( _( "Error while reading temporary file" ), RPT_SEVERITY_ERROR );
719 }
720
721 std::getline( KuKdfile, line );
722 }
723 else
724 {
725 Report( _( "Error while creating temporary output file" ), RPT_SEVERITY_ERROR );
726 }
727
728 if( std::remove( outputFileName.c_str() ) )
729 {
730 Report( _( "Cannot remove temporary output file" ), RPT_SEVERITY_WARNING );
731 }
732
733 m_Ku = std::move( ku );
734 m_Kd = std::move( kd );
735 m_t = std::move( t );
736}
737
738
740 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
741 const KIBIS_PARAMETER& aParam, int aIndex )
742{
743 IBIS_CORNER supply = aParam.m_supply;
744 IBIS_CORNER ccomp = aParam.m_Ccomp;
745 KIBIS_WAVEFORM* wave = aParam.m_waveform;
746
747 std::string simul = "";
748
749 simul += "*THIS IS NOT A VALID SPICE MODEL.\n";
750 simul += "*This part is intended to be executed by Kibis internally.\n";
751 simul += "*You should not be able to read this.\n\n";
752
753 simul += ".SUBCKT DRIVER";
754 simul += std::to_string( aIndex );
755 simul += " POWER GND PIN \n"; // 1: POWER, 2:GND, 3:PIN
756
757 simul += "Vdummy 2 PIN 0\n";
758
759 if( ( aPair.first->m_R_dut != 0 ) || ( aPair.first->m_L_dut != 0 )
760 || ( aPair.first->m_C_dut != 0 ) )
761 {
762 Report( _( "Kibis does not support DUT values yet. "
763 "https://ibis.org/summits/nov16a/chen.pdf" ),
765 }
766
767 simul += "\n";
768 simul += "CCPOMP 2 GND ";
769 simul += doubleToString( aModel.m_C_comp.value[ccomp] ); //@TODO: Check the corner ?
770 simul += "\n";
771
772 const IbisWaveform* risingWF = aPair.first;
773 const IbisWaveform* fallingWF = aPair.second;
774
775 switch( wave->GetType() )
776 {
777 case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
778 case KIBIS_WAVEFORM_TYPE::PRBS:
779 {
780 wave->Check( risingWF, fallingWF );
781 std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
782 bits = SimplifyBitSequence( bits );
783 simul += aModel.generateSquareWave( "DIE0", "GND", bits, aPair, aParam );
784 break;
785 }
786 case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
787 {
788 const IbisWaveform* waveform = wave->inverted ? risingWF : fallingWF;
789 simul += "Vsig DIE0 GND ";
790 simul += doubleToString( waveform->m_table.m_entries.at( 0 ).V.value[supply] );
791 simul += "\n";
792 break;
793 }
794 case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
795 {
796 const IbisWaveform* waveform = wave->inverted ? fallingWF : risingWF;
797 simul += "Vsig DIE0 GND ";
798 simul += doubleToString( waveform->m_table.m_entries.at( 0 ).V.value[supply] );
799 simul += "\n";
800 break;
801 }
802 case KIBIS_WAVEFORM_TYPE::NONE:
803 case KIBIS_WAVEFORM_TYPE::HIGH_Z:
804 default:
805 break;
806 }
807
808 simul += addDie( aModel, aParam, 0 );
809
810 simul += "\n.ENDS DRIVER\n\n";
811 return simul;
812}
813
814
816 const std::pair<IbisWaveform*, IbisWaveform*>& aPair,
817 const KIBIS_PARAMETER& aParam )
818{
819 IBIS_CORNER supply = aParam.m_supply;
820 const KIBIS_WAVEFORM* wave = aParam.m_waveform;
821
822 std::string simul = "";
823
824 if( !wave )
825 return;
826
827 if( wave->GetType() == KIBIS_WAVEFORM_TYPE::NONE )
828 {
829 //@TODO , there could be some current flowing through pullup / pulldown transistors, even when off
830 std::vector<double> ku, kd, t;
831 ku.push_back( 0 );
832 kd.push_back( 0 );
833 t.push_back( 0 );
834 m_Ku = std::move( ku );
835 m_Kd = std::move( kd );
836 m_t = std::move( t );
837 }
838 else
839 {
840 simul += KuKdDriver( aModel, aPair, aParam, 0 );
841 simul += "\n x1 3 0 1 DRIVER0 \n";
842
843 simul += "VCC 3 0 ";
844 simul += doubleToString( aModel.m_voltageRange.value[supply] );
845 simul += "\n";
846 //simul += "Vpin x1.DIE 0 1 \n"
847 simul += "Lfixture 1 4 ";
848 simul += doubleToString( aPair.first->m_L_fixture );
849 simul += "\n";
850 simul += "Rfixture 4 5 ";
851 simul += doubleToString( aPair.first->m_R_fixture );
852 simul += "\n";
853 simul += "Cfixture 4 0 ";
854 simul += doubleToString( aPair.first->m_C_fixture );
855 simul += "\n";
856 simul += "Vfixture 5 0 ";
857 simul += doubleToString( aPair.first->m_V_fixture );
858 simul += "\n";
859 simul += "VmeasIout x1.DIE0 x1.2 0\n";
860 simul += "VmeasPD 0 x1.PD_GND0 0\n";
861 simul += "VmeasPU x1.PU_PWR0 3 0\n";
862 simul += "VmeasPC x1.PC_PWR0 3 0\n";
863 simul += "VmeasGC 0 x1.GC_GND0 0\n";
864
865 if( aModel.HasPullup() && aModel.HasPulldown() )
866 {
867 Report( _( "Model has only one waveform pair, reduced accuracy" ),
869 simul += "Bku KU 0 v=( (i(VmeasIout)-i(VmeasPC)-i(VmeasGC)-i(VmeasPD) "
870 ")/(i(VmeasPU)-i(VmeasPD)))\n";
871 simul += "Bkd KD 0 v=(1-v(KU))\n";
872 }
873
874 else if( !aModel.HasPullup() && aModel.HasPulldown() )
875 {
876 simul += "Bku KD 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPD)))\n";
877 simul += "Bkd KU 0 v=0\n";
878 }
879
880 else if( aModel.HasPullup() && !aModel.HasPulldown() )
881 {
882 simul += "Bku KU 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPU)))\n";
883 simul += "Bkd KD 0 v=0\n";
884 }
885 else
886 {
887 Report( _( "Driver needs at least a pullup or a pulldown" ), RPT_SEVERITY_ERROR );
888 }
889
890 switch( wave->GetType() )
891 {
892 case KIBIS_WAVEFORM_TYPE::PRBS:
893 case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
894 {
895 double duration = wave->GetDuration();
896 simul += ".tran 0.1n ";
897 simul += doubleToString( duration );
898 simul += "\n";
899 break;
900 }
901 case KIBIS_WAVEFORM_TYPE::HIGH_Z:
902 case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
903 case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
904 default:
905 simul += ".tran 0.5 1 \n"; //
906 }
907
908 //simul += ".dc Vpin -5 5 0.1\n";
909 simul += ".control run \n";
910 simul += "set filetype=ascii\n";
911 simul += "run \n";
912 //simul += "plot v(x1.DIE0) i(VmeasIout) i(VmeasPD) i(VmeasPU) i(VmeasPC) i(VmeasGC)\n";
913 //simul += "plot v(KU) v(KD)\n";
914
915 std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
916 simul += "write '" + outputFileName + "' v(KU) v(KD)\n";
917 simul += "quit\n";
918 simul += ".endc \n";
919 simul += ".end \n";
920
921 getKuKdFromFile( simul );
922 }
923}
924
925
927{
928 std::vector<double> ku, kd, t;
929 const KIBIS_WAVEFORM* wave = aParam.m_waveform;
930 const IBIS_CORNER& supply = aParam.m_supply;
931
932 if( !wave )
933 return;
934
935 switch( wave->GetType() )
936 {
937 case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
938 case KIBIS_WAVEFORM_TYPE::PRBS:
939 {
940 wave->Check( aModel.m_ramp.m_rising, aModel.m_ramp.m_falling );
941 std::vector<std::pair<int, double>> bits = wave->GenerateBitSequence();
942 bits = SimplifyBitSequence( bits );
943
944 for( const std::pair<int, double>& bit : bits )
945 {
946 ku.push_back( bit.first ? 0 : 1 );
947 kd.push_back( bit.first ? 1 : 0 );
948 t.push_back( bit.second );
949 ku.push_back( bit.first ? 1 : 0 );
950 kd.push_back( bit.first ? 0 : 1 );
951 t.push_back( bit.second
952 + ( bit.first ? +aModel.m_ramp.m_rising.value[supply].m_dt
953 : aModel.m_ramp.m_falling.value[supply].m_dt )
954 / 0.6 );
955 // 0.6 because ibis only gives 20%-80% time
956 }
957 break;
958 }
959 case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
960 {
961 ku.push_back( wave->inverted ? 0 : 1 );
962 kd.push_back( wave->inverted ? 1 : 0 );
963 t.push_back( 0 );
964 break;
965 }
966 case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
967 {
968 ku.push_back( wave->inverted ? 1 : 0 );
969 kd.push_back( wave->inverted ? 0 : 1 );
970 t.push_back( 0 );
971 break;
972 }
973 case KIBIS_WAVEFORM_TYPE::HIGH_Z:
974 case KIBIS_WAVEFORM_TYPE::NONE:
975 default:
976 ku.push_back( 0 );
977 kd.push_back( 0 );
978 t.push_back( 0 );
979 }
980
981 m_Ku = std::move( ku );
982 m_Kd = std::move( kd );
983 m_t = std::move( t );
984}
985
986
988 const std::pair<IbisWaveform*, IbisWaveform*>& aPair1,
989 const std::pair<IbisWaveform*, IbisWaveform*>& aPair2,
990 const KIBIS_PARAMETER& aParam )
991{
992 std::string simul = "";
993 const IBIS_CORNER supply = aParam.m_supply;
994 const KIBIS_WAVEFORM* wave = aParam.m_waveform;
995
996 if( !wave )
997 return;
998
999 if( wave->GetType() == KIBIS_WAVEFORM_TYPE::NONE )
1000 {
1001 //@TODO , there could be some current flowing through pullup / pulldown transistors, even when off
1002 std::vector<double> ku, kd, t;
1003 ku.push_back( 0 );
1004 kd.push_back( 0 );
1005 t.push_back( 0 );
1006 m_Ku = std::move( ku );
1007 m_Kd = std::move( kd );
1008 m_t = std::move( t );
1009 }
1010 else
1011 {
1012 simul += KuKdDriver( aModel, aPair1, aParam, 0 );
1013 simul += KuKdDriver( aModel, aPair2, aParam, 1 );
1014 simul += "\n x1 3 0 1 DRIVER0 \n";
1015
1016 simul += "VCC 3 0 ";
1017 simul += doubleToString( aModel.m_voltageRange.value[supply] );
1018 simul += "\n";
1019 //simul += "Vpin x1.DIE 0 1 \n"
1020 simul += "Lfixture0 1 4 ";
1021 simul += doubleToString( aPair1.first->m_L_fixture );
1022 simul += "\n";
1023 simul += "Rfixture0 4 5 ";
1024 simul += doubleToString( aPair1.first->m_R_fixture );
1025 simul += "\n";
1026 simul += "Cfixture0 4 0 ";
1027 simul += doubleToString( aPair1.first->m_C_fixture );
1028 simul += "\n";
1029 simul += "Vfixture0 5 0 ";
1030 simul += doubleToString( aPair1.first->m_V_fixture );
1031 simul += "\n";
1032 simul += "VmeasIout0 x1.2 x1.DIE0 0\n";
1033 simul += "VmeasPD0 0 x1.PD_GND0 0\n";
1034 simul += "VmeasPU0 x1.PU_PWR0 3 0\n";
1035 simul += "VmeasPC0 x1.PC_PWR0 3 0\n";
1036 simul += "VmeasGC0 0 x1.GC_GND0 0\n";
1037
1038
1039 simul += "\n x2 3 0 7 DRIVER1 \n";
1040 //simul += "Vpin x1.DIE 0 1 \n"
1041 simul += "Lfixture1 7 8 ";
1042 simul += doubleToString( aPair2.first->m_L_fixture );
1043 simul += "\n";
1044 simul += "Rfixture1 8 9 ";
1045 simul += doubleToString( aPair2.first->m_R_fixture );
1046 simul += "\n";
1047 simul += "Cfixture1 8 0 ";
1048 simul += doubleToString( aPair2.first->m_C_fixture );
1049 simul += "\n";
1050 simul += "Vfixture1 9 0 ";
1051 simul += doubleToString( aPair2.first->m_V_fixture );
1052 simul += "\n";
1053 simul += "VmeasIout1 x2.2 x2.DIE0 0\n";
1054 simul += "VmeasPD1 0 x2.PD_GND0 0\n";
1055 simul += "VmeasPU1 x2.PU_PWR0 3 0\n";
1056 simul += "VmeasPC1 x2.PC_PWR0 3 0\n";
1057 simul += "VmeasGC1 0 x2.GC_GND0 0\n";
1058
1059 if( aModel.HasPullup() && aModel.HasPulldown() )
1060 {
1061 simul +=
1062 "Bku KU 0 v=( ( i(VmeasPD1) * ( i(VmeasIout0) + i(VmeasPC0) + i(VmeasGC0) ) - "
1063 "i(VmeasPD0) * ( i(VmeasIout1) + i(VmeasPC1) + i(VmeasGC1) ) )/ ( i(VmeasPU1) "
1064 "* "
1065 "i(VmeasPD0) - i(VmeasPU0) * i(VmeasPD1) ) )\n";
1066 simul +=
1067 "Bkd KD 0 v=( ( i(VmeasPU1) * ( i(VmeasIout0) + i(VmeasPC0) + i(VmeasGC0) ) - "
1068 "i(VmeasPU0) * ( i(VmeasIout1) + i(VmeasPC1) + i(VmeasGC1) ) )/ ( i(VmeasPD1) "
1069 "* "
1070 "i(VmeasPU0) - i(VmeasPD0) * i(VmeasPU1) ) )\n";
1071 //simul += "Bkd KD 0 v=(1-v(KU))\n";
1072 }
1073
1074 else if( !aModel.HasPullup() && aModel.HasPulldown() )
1075 {
1076 Report( _( "There are two waveform pairs, but only one transistor. More equations than "
1077 "unknowns." ),
1079 simul += "Bku KD 0 v=( ( i(VmeasIout0)+i(VmeasPC0)+i(VmeasGC0) )/(i(VmeasPD0)))\n";
1080 simul += "Bkd KU 0 v=0\n";
1081 }
1082
1083 else if( aModel.HasPullup() && !aModel.HasPulldown() )
1084 {
1085 Report( _( "There are two waveform pairs, but only one transistor. More equations than "
1086 "unknowns." ),
1088 simul += "Bku KU 0 v=( ( i(VmeasIout)+i(VmeasPC)+i(VmeasGC) )/(i(VmeasPU)))\n";
1089 simul += "Bkd KD 0 v=0\n";
1090 }
1091 else
1092 {
1093 Report( _( "Driver needs at least a pullup or a pulldown" ), RPT_SEVERITY_ERROR );
1094 }
1095
1096 switch( wave->GetType() )
1097 {
1098 case KIBIS_WAVEFORM_TYPE::RECTANGULAR:
1099 case KIBIS_WAVEFORM_TYPE::PRBS:
1100 {
1101 double duration = wave->GetDuration();
1102 simul += ".tran 0.1n ";
1103 simul += doubleToString( duration );
1104 simul += "\n";
1105 break;
1106 }
1107 case KIBIS_WAVEFORM_TYPE::HIGH_Z:
1108 case KIBIS_WAVEFORM_TYPE::STUCK_LOW:
1109 case KIBIS_WAVEFORM_TYPE::STUCK_HIGH:
1110 default:
1111 simul += ".tran 0.5 1 \n"; //
1112 }
1113
1114 //simul += ".dc Vpin -5 5 0.1\n";
1115 simul += ".control run \n";
1116 simul += "set filetype=ascii\n";
1117 simul += "run \n";
1118 simul += "plot v(KU) v(KD)\n";
1119 //simul += "plot v(x1.DIE0) \n";
1120 std::string outputFileName = m_topLevel->m_cacheDir + "temp_output.spice";
1121 simul += "write '" + outputFileName + "' v(KU) v(KD)\n";
1122 simul += "quit\n";
1123 simul += ".endc \n";
1124 simul += ".end \n";
1125
1126 getKuKdFromFile( simul );
1127 }
1128}
1129
1130
1131bool KIBIS_PIN::writeSpiceDriver( std::string& aDest, const std::string& aName, KIBIS_MODEL& aModel,
1132 const KIBIS_PARAMETER& aParam )
1133{
1134 bool status = true;
1135
1136 switch( aModel.m_type )
1137 {
1138 case IBIS_MODEL_TYPE::OUTPUT:
1139 case IBIS_MODEL_TYPE::IO:
1140 case IBIS_MODEL_TYPE::THREE_STATE:
1141 case IBIS_MODEL_TYPE::OPEN_DRAIN:
1142 case IBIS_MODEL_TYPE::IO_OPEN_DRAIN:
1143 case IBIS_MODEL_TYPE::OPEN_SINK:
1144 case IBIS_MODEL_TYPE::IO_OPEN_SINK:
1145 case IBIS_MODEL_TYPE::OPEN_SOURCE:
1146 case IBIS_MODEL_TYPE::IO_OPEN_SOURCE:
1147 case IBIS_MODEL_TYPE::OUTPUT_ECL:
1148 case IBIS_MODEL_TYPE::IO_ECL:
1149 case IBIS_MODEL_TYPE::THREE_STATE_ECL:
1150 {
1151 std::string result;
1152 std::string tmp;
1153
1154 result = "\n*Driver model generated by Kicad using Ibis data. ";
1155
1156 result += "\n*Pin number: ";
1157 result += m_pinNumber;
1158 result += "\n*Signal name: ";
1159 result += m_signalName;
1160 result += "\n*Model: ";
1161 result += aModel.m_name;
1162 result += "\n.SUBCKT ";
1163 result += aName;
1164 result += " GND PIN \n";
1165 result += "\n";
1166
1167 result += "RPIN 1 PIN ";
1168 result += doubleToString( m_Rpin.value[aParam.m_Rpin] );
1169 result += "\n";
1170 result += "LPIN DIE0 1 ";
1171 result += doubleToString( m_Lpin.value[aParam.m_Lpin] );
1172 result += "\n";
1173 result += "CPIN PIN GND ";
1174 result += doubleToString( m_Cpin.value[aParam.m_Cpin] );
1175 result += "\n";
1176
1177 std::vector<std::pair<IbisWaveform*, IbisWaveform*>> wfPairs = aModel.waveformPairs();
1179
1180 if( wfPairs.size() < 1 || accuracy <= KIBIS_ACCURACY::LEVEL_0 )
1181 {
1182 if( accuracy > KIBIS_ACCURACY::LEVEL_0 )
1183 {
1184 Report( _( "Model has no waveform pair, using [Ramp] instead, poor accuracy" ),
1186 }
1187
1188 getKuKdNoWaveform( aModel, aParam );
1189 }
1190 else if( wfPairs.size() == 1 || accuracy <= KIBIS_ACCURACY::LEVEL_1 )
1191 {
1192 getKuKdOneWaveform( aModel, wfPairs.at( 0 ), aParam );
1193 }
1194 else
1195 {
1196 if( wfPairs.size() > 2 || accuracy <= KIBIS_ACCURACY::LEVEL_2 )
1197 {
1198 Report( _( "Model has more than 2 waveform pairs, using the first two." ),
1200 }
1201
1202 getKuKdTwoWaveforms( aModel, wfPairs.at( 0 ), wfPairs.at( 1 ), aParam );
1203 }
1204
1205 result += "Vku KU GND pwl ( ";
1206
1207 for( size_t i = 0; i < m_t.size(); i++ )
1208 {
1209 result += doubleToString( m_t.at( i ) );
1210 result += " ";
1211 result += doubleToString( m_Ku.at( i ) );
1212 result += " ";
1213 }
1214
1215 result += ") \n";
1216
1217
1218 result += "Vkd KD GND pwl ( ";
1219
1220 for( size_t i = 0; i < m_t.size(); i++ )
1221 {
1222 result += doubleToString( m_t.at( i ) );
1223 result += " ";
1224 result += doubleToString( m_Kd.at( i ) );
1225 result += " ";
1226 }
1227
1228 result += ") \n";
1229
1230 result += aModel.SpiceDie( aParam, 0 );
1231
1232 result += "\n.ENDS DRIVER\n\n";
1233
1234 aDest += result;
1235 break;
1236 }
1237 default:
1238 Report( _( "Invalid model type for a driver." ), RPT_SEVERITY_ERROR );
1239 status = false;
1240 }
1241
1242 return status;
1243}
1244
1245
1246bool KIBIS_PIN::writeSpiceDevice( std::string& aDest, const std::string& aName, KIBIS_MODEL& aModel,
1247 const KIBIS_PARAMETER& aParam )
1248{
1249 bool status = true;
1250
1251 switch( aModel.m_type )
1252 {
1253 case IBIS_MODEL_TYPE::INPUT_STD:
1254 case IBIS_MODEL_TYPE::IO:
1255 case IBIS_MODEL_TYPE::IO_OPEN_DRAIN:
1256 case IBIS_MODEL_TYPE::IO_OPEN_SINK:
1257 case IBIS_MODEL_TYPE::IO_OPEN_SOURCE:
1258 case IBIS_MODEL_TYPE::IO_ECL:
1259 {
1260 std::string result;
1261
1262 result += "\n";
1263 result = "*Device model generated by Kicad using Ibis data.";
1264 result += "\n.SUBCKT ";
1265 result += aName;
1266 result += " GND PIN\n";
1267 result += "\n";
1268 result += "\n";
1269 result += "RPIN 1 PIN ";
1270 result += doubleToString( m_Rpin.value[aParam.m_Rpin] );
1271 result += "\n";
1272 result += "LPIN DIE0 1 ";
1273 result += doubleToString( m_Lpin.value[aParam.m_Lpin] );
1274 result += "\n";
1275 result += "CPIN PIN GND ";
1276 result += doubleToString( m_Cpin.value[aParam.m_Cpin] );
1277 result += "\n";
1278
1279
1280 result += "Vku KU GND pwl ( 0 0 )\n";
1281 result += "Vkd KD GND pwl ( 0 0 )\n";
1282
1283 result += aModel.SpiceDie( aParam, 0 );
1284
1285 result += "\n.ENDS DRIVER\n\n";
1286
1287 aDest = std::move( result );
1288 break;
1289 }
1290 default:
1291 Report( _( "Invalid model type for a device" ), RPT_SEVERITY_ERROR );
1292 status = false;
1293 }
1294
1295 return status;
1296}
1297
1298
1299bool KIBIS_PIN::writeSpiceDiffDriver( std::string& aDest, const std::string& aName,
1300 KIBIS_MODEL& aModel, const KIBIS_PARAMETER& aParam )
1301{
1302 bool status = true;
1303 KIBIS_WAVEFORM* wave = aParam.m_waveform;
1304
1305 if( !wave )
1306 return false;
1307
1308 std::string result;
1309 result = "\n*Differential driver model generated by Kicad using Ibis data. ";
1310
1311 result += "\n.SUBCKT ";
1312 result += aName;
1313 result += " GND PIN_P PIN_N\n";
1314 result += "\n";
1315
1316 status &= writeSpiceDriver( result, aName + "_P", aModel, aParam );
1317 wave->inverted = !wave->inverted;
1318 status &= writeSpiceDriver( result, aName + "_N", aModel, aParam );
1319 wave->inverted = !wave->inverted;
1320
1321
1322 result += "\n";
1323 result += "x1 GND PIN_P " + aName + "_P \n";
1324 result += "x2 GND PIN_N " + aName + "_N \n";
1325 result += "\n";
1326
1327 result += "\n.ENDS " + aName + "\n\n";
1328
1329 if( status )
1330 aDest += result;
1331
1332 return status;
1333}
1334
1335
1336bool KIBIS_PIN::writeSpiceDiffDevice( std::string& aDest, const std::string& aName,
1337 KIBIS_MODEL& aModel, const KIBIS_PARAMETER& aParam )
1338{
1339 bool status = true;
1340
1341 std::string result;
1342 result = "\n*Differential device model generated by Kicad using Ibis data. ";
1343
1344 result += "\n.SUBCKT ";
1345 result += aName;
1346 result += " GND PIN_P PIN_N\n";
1347 result += "\n";
1348
1349 status &= writeSpiceDevice( result, aName + "_P", aModel, aParam );
1350 status &= writeSpiceDevice( result, aName + "_N", aModel, aParam );
1351
1352 result += "\n";
1353 result += "x1 GND PIN_P " + aName + "_P \n";
1354 result += "x2 GND PIN_N " + aName + "_N \n";
1355 result += "\n";
1356
1357 result += "\n.ENDS " + aName + "\n\n";
1358
1359 if( status )
1360 aDest += result;
1361
1362 return status;
1363}
1364
1365
1366KIBIS_MODEL* KIBIS::GetModel( const std::string& aName )
1367{
1368 for( KIBIS_MODEL& model : m_models )
1369 {
1370 if( model.m_name == aName )
1371 return &model;
1372 }
1373
1374 return nullptr;
1375}
1376
1377
1378KIBIS_COMPONENT* KIBIS::GetComponent( const std::string& aName )
1379{
1380 for( KIBIS_COMPONENT& cmp : m_components )
1381 {
1382 if( cmp.m_name == aName )
1383 return &cmp;
1384 }
1385
1386 return nullptr;
1387}
1388
1389
1390void KIBIS_PARAMETER::SetCornerFromString( IBIS_CORNER& aCorner, const std::string& aString )
1391{
1392 if( aString == "MIN" )
1393 aCorner = IBIS_CORNER::MIN;
1394 else if( aString == "MAX" )
1395 aCorner = IBIS_CORNER::MAX;
1396 else
1397 aCorner = IBIS_CORNER::TYP;
1398}
1399
1400
1401std::vector<std::pair<int, double>> KIBIS_WAVEFORM_STUCK_HIGH::GenerateBitSequence() const
1402{
1403 std::vector<std::pair<int, double>> bits;
1404 std::pair<int, double> bit;
1405 bit.first = inverted ? 1 : 0;
1406 bit.second = 0;
1407 return bits;
1408}
1409
1410
1411std::vector<std::pair<int, double>> KIBIS_WAVEFORM_STUCK_LOW::GenerateBitSequence() const
1412{
1413 std::vector<std::pair<int, double>> bits;
1414 std::pair<int, double> bit;
1415 bit.first = inverted ? 0 : 1;
1416 bit.second = 0;
1417 return bits;
1418}
1419
1420std::vector<std::pair<int, double>> KIBIS_WAVEFORM_HIGH_Z::GenerateBitSequence() const
1421{
1422 std::vector<std::pair<int, double>> bits;
1423 return bits;
1424}
1425
1426std::vector<std::pair<int, double>> KIBIS_WAVEFORM_RECTANGULAR::GenerateBitSequence() const
1427{
1428 std::vector<std::pair<int, double>> bits;
1429
1430 for( int i = 0; i < m_cycles; i++ )
1431 {
1432 std::pair<int, double> bit;
1433 bit.first = inverted ? 0 : 1;
1434 bit.second = ( m_ton + m_toff ) * i + m_delay;
1435 bits.push_back( bit );
1436
1437 bit.first = inverted ? 1 : 0;
1438 bit.second = ( m_ton + m_toff ) * i + m_delay + m_ton;
1439 bits.push_back( bit );
1440 }
1441
1442 return bits;
1443}
1444
1445
1446std::vector<std::pair<int, double>> KIBIS_WAVEFORM_PRBS::GenerateBitSequence() const
1447{
1448 std::vector<std::pair<int, double>> bitSequence;
1449 uint8_t polynomial = 0b1100000;
1450 //1100000 = x^7+x^6+1
1451 //10100 = x^5+x^3+1
1452 //110 = x^3+x^2+1
1453 uint8_t seed = 0x12; // Any non zero state
1454 uint8_t lfsr = seed;
1455
1456 if ( m_bitrate == 0 )
1457 return bitSequence;
1458
1459 double period = 1/m_bitrate;
1460 double t = 0;
1461
1462 wxASSERT( m_bits > 0 );
1463
1464 int bits = 0;
1465
1466 do
1467 {
1468 uint8_t lsb = lfsr & 0x01;
1469 bitSequence.emplace_back( ( static_cast<uint8_t>( inverted ) ^ lsb ? 1 : 0 ), t );
1470 lfsr = lfsr >> 1;
1471
1472 if ( lsb )
1473 lfsr ^= polynomial;
1474
1475 t += period;
1476
1477 } while ( ++bits < m_bits );
1478
1479 return bitSequence;
1480}
1481
1483 const IbisWaveform* aFallingWf ) const
1484{
1485 bool status = true;
1486
1487 if( m_cycles < 1 )
1488 {
1489 status = false;
1490 Report( _( "Number of cycles should be greater than 0." ), RPT_SEVERITY_ERROR );
1491 }
1492
1493 if( m_ton <= 0 )
1494 {
1495 status = false;
1496 Report( _( "ON time should be greater than 0." ), RPT_SEVERITY_ERROR );
1497 }
1498
1499 if( m_toff <= 0 )
1500 {
1501 status = false;
1502 Report( _( "OFF time should be greater than 0." ), RPT_SEVERITY_ERROR );
1503 }
1504
1505 if( aRisingWf )
1506 {
1507 if( m_ton < aRisingWf->m_table.m_entries.back().t )
1508 {
1509 status = false;
1510 Report( _( "Rising edge is longer than on time." ), RPT_SEVERITY_WARNING );
1511 }
1512 }
1513
1514 if( aFallingWf )
1515 {
1516 if( m_toff < aFallingWf->m_table.m_entries.back().t )
1517 {
1518 status = false;
1519 Report( _( "Falling edge is longer than off time." ), RPT_SEVERITY_WARNING );
1520 }
1521 }
1522
1523 status &= aRisingWf && aFallingWf;
1524
1525 return status;
1526}
1527
1528
1530 const dvdtTypMinMax& aFallingRp ) const
1531{
1532 bool status = true;
1533
1534 if( m_cycles < 1 )
1535 {
1536 status = false;
1537 Report( _( "Number of cycles should be greater than 0." ), RPT_SEVERITY_ERROR );
1538 }
1539
1540 if( m_ton <= 0 )
1541 {
1542 status = false;
1543 Report( _( "ON time should be greater than 0." ), RPT_SEVERITY_ERROR );
1544 }
1545
1546 if( m_toff <= 0 )
1547 {
1548 status = false;
1549 Report( _( "OFF time should be greater than 0." ), RPT_SEVERITY_ERROR );
1550 }
1551
1552 if( ( m_ton < aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 )
1553 || ( m_ton < aRisingRp.value[IBIS_CORNER::MIN].m_dt / 0.6 )
1554 || ( m_ton < aRisingRp.value[IBIS_CORNER::MAX].m_dt / 0.6 ) )
1555 {
1556 status = false;
1557 Report( _( "Rising edge is longer than ON time." ), RPT_SEVERITY_ERROR );
1558 }
1559
1560 if( ( m_toff < aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 )
1561 || ( m_toff < aFallingRp.value[IBIS_CORNER::MIN].m_dt / 0.6 )
1562 || ( m_toff < aFallingRp.value[IBIS_CORNER::MAX].m_dt / 0.6 ) )
1563 {
1564 status = false;
1565 Report( _( "Falling edge is longer than OFF time." ), RPT_SEVERITY_ERROR );
1566 }
1567
1568 return status;
1569}
1570
1571
1573 const dvdtTypMinMax& aFallingRp ) const
1574{
1575 bool status = true;
1576
1577 if( m_bitrate <= 0 )
1578 {
1579 status = false;
1580 Report( _( "Bitrate should be greater than 0." ), RPT_SEVERITY_ERROR );
1581 }
1582
1583 if( m_bits <= 0 )
1584 {
1585 status = false;
1586 Report( _( "Number of bits should be greater than 0." ), RPT_SEVERITY_ERROR );
1587 }
1588
1589 if( m_bitrate
1590 && ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
1591 + aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) )
1592 && ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
1593 + aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) )
1594 && ( ( 1 / m_bitrate ) < ( aRisingRp.value[IBIS_CORNER::TYP].m_dt / 0.6
1595 + aFallingRp.value[IBIS_CORNER::TYP].m_dt / 0.6 ) ) )
1596 {
1597 status = false;
1598 Report( _( "Bitrate is too high for rising / falling edges" ), RPT_SEVERITY_ERROR );
1599 }
1600
1601 return status;
1602}
1603
1605 const IbisWaveform* aFallingWf ) const
1606{
1607 bool status = true;
1608
1609 if( m_bitrate <= 0 )
1610 {
1611 status = false;
1612 Report( _( "Bitrate should be greater than 0." ), RPT_SEVERITY_ERROR );
1613 }
1614
1615 if( m_bits <= 0 )
1616 {
1617 status = false;
1618 Report( _( "Number of bits should be greater than 0." ), RPT_SEVERITY_ERROR );
1619 }
1620
1621 if( m_bitrate && aRisingWf && aFallingWf
1622 && ( ( 1 / m_bitrate ) < ( aRisingWf->m_table.m_entries.back().t
1623 + aFallingWf->m_table.m_entries.back().t ) ) )
1624 {
1625 status = false;
1626 Report( _( "Bitrate could be too high for rising / falling edges" ), RPT_SEVERITY_WARNING );
1627 }
1628
1629 return status;
1630}
void Report(const std::string &aMsg, SEVERITY aSeverity=RPT_SEVERITY_INFO) const
Print a message.
Definition: ibis_parser.h:67
REPORTER * m_Reporter
Definition: ibis_parser.h:74
static std::string doubleToString(double aNumber)
Convert a double to string using scientific notation.
std::vector< IVtableEntry > m_entries
Definition: ibis_parser.h:388
std::string Spice(int aN, const std::string &aPort1, const std::string &aPort2, const std::string &aModelName, IBIS_CORNER aCorner) const
Interpolate the IV table.
TypMinMaxValue m_Cpkg
Definition: ibis_parser.h:234
TypMinMaxValue m_Lpkg
Definition: ibis_parser.h:233
TypMinMaxValue m_Rpkg
Definition: ibis_parser.h:232
std::string m_signalName
Definition: ibis_parser.h:251
std::string m_pinName
Definition: ibis_parser.h:250
std::string m_modelName
Definition: ibis_parser.h:252
std::string m_manufacturer
Definition: ibis_parser.h:327
IbisComponentPackage m_package
Definition: ibis_parser.h:328
IbisDiffPin m_diffPin
Definition: ibis_parser.h:334
std::string m_name
Definition: ibis_parser.h:326
std::vector< IbisComponentPin > m_pins
Definition: ibis_parser.h:329
std::string pinB
Definition: ibis_parser.h:298
std::string pinA
Definition: ibis_parser.h:297
std::vector< IbisDiffPinEntry > m_entries
Definition: ibis_parser.h:311
std::vector< IbisComponent > m_components
Definition: ibis_parser.h:655
IbisHeader m_header
Definition: ibis_parser.h:654
std::vector< IbisModel > m_models
Definition: ibis_parser.h:657
std::vector< IbisModelSelector > m_modelSelectors
Definition: ibis_parser.h:656
std::string m_fileName
Definition: ibis_parser.h:198
std::string m_copyright
Definition: ibis_parser.h:203
std::string m_notes
Definition: ibis_parser.h:201
double m_ibisVersion
Definition: ibis_parser.h:196
std::string m_date
Definition: ibis_parser.h:200
double m_fileRevision
Definition: ibis_parser.h:197
std::string m_disclaimer
Definition: ibis_parser.h:202
std::string m_modelName
Definition: ibis_parser.h:343
std::string m_modelDescription
Definition: ibis_parser.h:344
std::string m_name
Definition: ibis_parser.h:358
std::vector< IbisModelSelectorEntry > m_models
Definition: ibis_parser.h:359
IBIS_MODEL_TYPE m_type
Definition: ibis_parser.h:582
double m_cref
Definition: ibis_parser.h:589
IVtable m_pullup
Definition: ibis_parser.h:608
TypMinMaxValue m_Cac
Definition: ibis_parser.h:605
TypMinMaxValue m_pullupReference
Definition: ibis_parser.h:598
double m_vmeas
Definition: ibis_parser.h:590
IVtable m_pulldown
Definition: ibis_parser.h:609
TypMinMaxValue m_Rac
Definition: ibis_parser.h:604
std::vector< IbisWaveform * > m_risingWaveforms
Definition: ibis_parser.h:610
IVtable m_POWERClamp
Definition: ibis_parser.h:607
TypMinMaxValue m_Rgnd
Definition: ibis_parser.h:602
TypMinMaxValue m_POWERClampReference
Definition: ibis_parser.h:601
IVtable m_GNDClamp
Definition: ibis_parser.h:606
IbisRamp m_ramp
Definition: ibis_parser.h:612
IBIS_MODEL_POLARITY m_polarity
Definition: ibis_parser.h:592
TypMinMaxValue m_C_comp
Definition: ibis_parser.h:595
double m_rref
Definition: ibis_parser.h:588
IBIS_MODEL_ENABLE m_enable
Definition: ibis_parser.h:591
TypMinMaxValue m_temperatureRange
Definition: ibis_parser.h:597
std::vector< IbisWaveform * > m_fallingWaveforms
Definition: ibis_parser.h:611
TypMinMaxValue m_pulldownReference
Definition: ibis_parser.h:599
double m_vref
Definition: ibis_parser.h:587
TypMinMaxValue m_GNDClampReference
Definition: ibis_parser.h:600
double m_vinh
Definition: ibis_parser.h:586
double m_vinl
Definition: ibis_parser.h:585
TypMinMaxValue m_voltageRange
Definition: ibis_parser.h:596
TypMinMaxValue m_Rpower
Definition: ibis_parser.h:603
std::string m_name
Definition: ibis_parser.h:581
bool ParseFile(const std::string &aFileName)
Parse a file.
bool m_parrot
Definition: ibis_parser.h:702
IbisFile m_ibisFile
Definition: ibis_parser.h:712
dvdtTypMinMax m_rising
Definition: ibis_parser.h:511
dvdtTypMinMax m_falling
Definition: ibis_parser.h:510
double m_L_fixture
Definition: ibis_parser.h:540
double m_V_fixture
Definition: ibis_parser.h:541
VTtable m_table
Definition: ibis_parser.h:533
double m_V_fixture_min
Definition: ibis_parser.h:542
double m_V_fixture_max
Definition: ibis_parser.h:543
double m_R_fixture
Definition: ibis_parser.h:538
double m_C_fixture
Definition: ibis_parser.h:539
bool m_valid
Definition: kibis.h:57
KIBIS * m_topLevel
Definition: kibis.h:56
KIBIS_BASE(KIBIS *aTopLevel)
Definition: kibis.cpp:68
KIBIS_COMPONENT(KIBIS &aToplevel, const IbisComponent &aSource, IbisParser &aParser)
Definition: kibis.cpp:306
std::vector< KIBIS_PIN > m_pins
Definition: kibis.h:456
std::string m_manufacturer
Name of the manufacturer.
Definition: kibis.h:454
std::string m_name
Name of the component.
Definition: kibis.h:452
KIBIS_PIN * GetPin(const std::string &aPinNumber)
Get a pin by its number ( 1, 2, A1, A2, ... )
Definition: kibis.cpp:330
KIBIS_FILE(KIBIS &aTopLevel)
Definition: kibis.cpp:137
std::string m_notes
Definition: kibis.h:238
double m_ibisVersion
Definition: kibis.h:235
std::string m_date
Definition: kibis.h:236
bool Init(const IbisParser &aParser)
Definition: kibis.cpp:145
std::string m_fileName
Definition: kibis.h:233
std::string m_copyright
Definition: kibis.h:240
std::string m_disclaimer
Definition: kibis.h:239
double m_fileRev
Definition: kibis.h:234
std::vector< IbisWaveform * > m_fallingWaveforms
Definition: kibis.h:281
IbisWaveform TrimWaveform(const IbisWaveform &aIn) const
Copy a waveform, and substract the first value to all samples.
Definition: kibis.cpp:441
IBIS_MODEL_ENABLE m_enable
Definition: kibis.h:261
double m_vref
Definition: kibis.h:257
std::string m_name
Definition: kibis.h:250
bool HasPOWERClamp() const
Return true if the model has a clamp diode to the power net.
Definition: kibis.cpp:495
double m_vmeas
Definition: kibis.h:260
std::vector< IbisWaveform * > m_risingWaveforms
Definition: kibis.h:280
TypMinMaxValue m_Cac
Definition: kibis.h:275
double m_vinh
Definition: kibis.h:256
double m_rref
Definition: kibis.h:258
bool HasPullup() const
Return true if the model has a pullup transistor.
Definition: kibis.cpp:483
bool HasGNDClamp() const
Return true if the model has a clamp diode to the gnd net.
Definition: kibis.cpp:489
TypMinMaxValue m_pulldownReference
Definition: kibis.h:269
TypMinMaxValue m_GNDClampReference
Definition: kibis.h:270
TypMinMaxValue m_Rpower
Definition: kibis.h:273
bool HasPulldown() const
Return true if the model has a pulldown transistor.
Definition: kibis.cpp:477
IBIS_MODEL_TYPE m_type
Definition: kibis.h:252
IbisRamp m_ramp
Definition: kibis.h:282
IVtable m_pullup
Definition: kibis.h:278
IBIS_MODEL_POLARITY m_polarity
Definition: kibis.h:262
double m_cref
Definition: kibis.h:259
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.
Definition: kibis.cpp:501
TypMinMaxValue m_Rac
Definition: kibis.h:274
TypMinMaxValue m_temperatureRange
Definition: kibis.h:267
TypMinMaxValue m_voltageRange
Definition: kibis.h:266
IVtable m_GNDClamp
Definition: kibis.h:276
TypMinMaxValue m_Rgnd
Definition: kibis.h:272
std::string m_description
Definition: kibis.h:251
KIBIS_MODEL(KIBIS &aTopLevel, const IbisModel &aSource, IbisParser &aParser)
Definition: kibis.cpp:236
IVtable m_POWERClamp
Definition: kibis.h:277
TypMinMaxValue m_pullupReference
Definition: kibis.h:268
std::vector< std::pair< IbisWaveform *, IbisWaveform * > > waveformPairs()
Create waveform pairs.
Definition: kibis.cpp:341
TypMinMaxValue m_POWERClampReference
Definition: kibis.h:271
TypMinMaxValue m_C_comp
Definition: kibis.h:265
std::string SpiceDie(const KIBIS_PARAMETER &aParam, int aIndex) const
Generate the spice directive to simulate the die.
Definition: kibis.cpp:368
IVtable m_pulldown
Definition: kibis.h:279
double m_vinl
Definition: kibis.h:255
IBIS_CORNER m_supply
Definition: kibis.h:220
IBIS_CORNER m_Cpin
Definition: kibis.h:218
KIBIS_ACCURACY m_accuracy
Definition: kibis.h:222
IBIS_CORNER m_Ccomp
Definition: kibis.h:219
IBIS_CORNER m_Lpin
Definition: kibis.h:217
IBIS_CORNER m_Rpin
Definition: kibis.h:216
void SetCornerFromString(IBIS_CORNER &aCorner, const std::string &aString)
Definition: kibis.cpp:1390
KIBIS_WAVEFORM * m_waveform
Definition: kibis.h:221
TypMinMaxValue m_Rpin
Resistance from die to pin.
Definition: kibis.h:355
bool writeSpiceDiffDriver(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition: kibis.cpp:1299
TypMinMaxValue m_Lpin
Inductance from die to pin.
Definition: kibis.h:357
void getKuKdFromFile(const std::string &aSimul)
Update m_Ku, m_Kd using with two waveform inputs.
Definition: kibis.cpp:646
KIBIS_COMPONENT * m_parent
Definition: kibis.h:361
std::vector< double > m_Ku
Definition: kibis.h:363
std::string m_pinNumber
Pin Number Examples : 1, 2, 3 ( or for BGA ), A1, A2, A3, etc...
Definition: kibis.h:352
std::string addDie(KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam, int aIndex)
Generate the spice directive to simulate the die for Ku/Kd estimation.
Definition: kibis.cpp:602
bool writeSpiceDevice(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition: kibis.cpp:1246
std::vector< KIBIS_MODEL * > m_models
Definition: kibis.h:365
std::vector< double > m_t
Definition: kibis.h:363
TypMinMaxValue m_Cpin
Capacitance from pin to GND.
Definition: kibis.h:359
std::string m_signalName
Name of the pin Examples : "VCC", "GPIOA", "CLK", etc...
Definition: kibis.h:348
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.
Definition: kibis.cpp:987
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.
Definition: kibis.cpp:815
bool writeSpiceDiffDevice(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition: kibis.cpp:1336
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.
Definition: kibis.cpp:739
KIBIS_PIN(KIBIS &aTopLevel, const IbisComponentPin &aPin, const IbisComponentPackage &aPackage, IbisParser &aParser, KIBIS_COMPONENT *aParent, std::vector< KIBIS_MODEL > &aModels)
Definition: kibis.cpp:162
std::vector< double > m_Kd
Definition: kibis.h:363
bool writeSpiceDriver(std::string &aDest, const std::string &aName, KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Definition: kibis.cpp:1131
KIBIS_PIN * m_complementaryPin
Definition: kibis.h:442
void getKuKdNoWaveform(KIBIS_MODEL &aModel, const KIBIS_PARAMETER &aParam)
Update m_Ku, m_Kd using no falling / rising waveform inputs ( low accuracy )
Definition: kibis.cpp:926
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1420
bool Check(const IbisWaveform *aRisingWf, const IbisWaveform *aFallingWf) const override
Definition: kibis.cpp:1604
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1446
double m_bitrate
Definition: kibis.h:138
bool Check(const IbisWaveform *aRisingWf, const IbisWaveform *aFallingWf) const override
Definition: kibis.cpp:1482
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1426
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1401
std::vector< std::pair< int, double > > GenerateBitSequence() const override
Definition: kibis.cpp:1411
virtual bool Check(const IbisWaveform *aRisingWf, const IbisWaveform *aFallingWf) const
Definition: kibis.h:92
KIBIS_WAVEFORM_TYPE GetType() const
Definition: kibis.h:80
bool inverted
Definition: kibis.h:82
virtual double GetDuration() const
Definition: kibis.h:81
virtual std::vector< std::pair< int, double > > GenerateBitSequence() const
Definition: kibis.h:85
Definition: kibis.h:467
std::vector< KIBIS_MODEL > m_models
Definition: kibis.h:478
KIBIS()
Constructor for unitialized KIBIS members.
Definition: kibis.h:470
std::vector< KIBIS_COMPONENT > m_components
Definition: kibis.h:477
KIBIS_MODEL * GetModel(const std::string &aName)
Return the model with name aName .
Definition: kibis.cpp:1366
KIBIS_COMPONENT * GetComponent(const std::string &aName)
Return the component with name aName .
Definition: kibis.cpp:1378
KIBIS_FILE m_file
Definition: kibis.h:479
std::string m_cacheDir
Absolute path of the directory that will be used for caching.
Definition: kibis.h:482
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:73
static std::shared_ptr< SPICE_SIMULATOR > CreateInstance(const std::string &aName)
double value[3]
Definition: ibis_parser.h:216
TypMinMaxValue V
Definition: ibis_parser.h:432
std::vector< VTtableEntry > m_entries
Definition: ibis_parser.h:443
dvdt value[3]
Definition: ibis_parser.h:495
double m_dt
Definition: ibis_parser.h:487
#define _(s)
IBIS_CORNER
Definition: ibis_parser.h:102
@ TYP
Definition: ibis_parser.h:103
@ MIN
Definition: ibis_parser.h:104
@ MAX
Definition: ibis_parser.h:105
std::vector< std::pair< int, double > > SimplifyBitSequence(const std::vector< std::pair< int, double > > &bits)
Definition: kibis.cpp:51
IBIS_CORNER ReverseLogic(IBIS_CORNER aIn)
Definition: kibis.cpp:82
KIBIS_ACCURACY
Accuracy level.
Definition: kibis.h:206
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
const int accuracy
int delta
#define ku