KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ibis_parser.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 (C) 2023 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 "ibis_parser.h"
34
35#include <sstream>
36#include <cstring> //for memcmp
37#include <iterator>
38#include <locale_io.h> // KiCad header
39
40// _() is used here to mark translatable strings in IBIS_REPORTER::Report()
41// However, currently non ASCII7 chars are nor correctly handled when printing messages
42// So we disable translations
43#if 0
44#include <wx/intl.h> // for _() macro and wxGetTranslation()
45#else
46#undef _
47#define _( x ) x
48#endif
49
50
51bool IbisParser::compareIbisWord( const std::string& stra, const std::string& strb )
52{
53 return std::equal( stra.begin(), stra.end(),
54 strb.begin(), strb.end(),
55 [](char a, char b)
56 {
57 return std::tolower(a) == std::tolower(b);
58 });
59}
60
62{
63 bool status = true;
64
65 if( m_dim < 1 )
66 {
67 Report( _( "Dimension of matrices should be >= 1." ), RPT_SEVERITY_ERROR );
68 status = false;
69 }
70
71 if( m_bandwidth < 1 )
72 {
73 Report( _( "Bandwidth of banded matrices should be >= 1." ), RPT_SEVERITY_ERROR );
74 status = false;
75 }
76
77 for( int i = 0; i < m_bandwidth * m_dim; i++ )
78 {
79 if( std::isnan( m_data[i] ) )
80 {
81 Report( _( "There are NaN elements in a matrix." ), RPT_SEVERITY_ERROR );
82 status = false;
83 }
84 }
85
86
87 return status;
88}
89
91{
92 bool status = true;
93
94 if( m_dim < 1 )
95 {
96 Report( _( "Dimension of matrices should be >= 1." ), RPT_SEVERITY_ERROR );
97 status = false;
98 }
99
100 for( int i = 0; i < m_dim * m_dim; i++ )
101 {
102 if( std::isnan( m_data[i] ) )
103 {
104 Report( _( "There are NaN elements in a matrix." ), RPT_SEVERITY_ERROR );
105 status = false;
106 }
107 }
108
109
110 return status;
111}
112
114{
115 bool status = true;
116
117 if( m_dim < 1 )
118 {
119 Report( _( "Dimension of matrices should be >= 1." ), RPT_SEVERITY_ERROR );
120 status = false;
121 }
122
123 for( int i = 0; i < m_dim * m_dim; i++ )
124 {
125 if( std::isnan( m_data[i] ) )
126 {
127 Report( _( "There are NaN elements in a matrix." ), RPT_SEVERITY_ERROR );
128 status = false;
129 }
130 }
131
132
133 return status;
134}
135
136bool isNumberNA( double aNumber )
137{
138 double NA = nan( NAN_NA );
139 return std::memcmp( &aNumber, &NA, sizeof NA ) == 0;
140}
141
143{
144 bool status = true;
145
146 if( std::isnan( value[IBIS_CORNER::TYP] ) )
147 status = false;
148 if( std::isnan( value[IBIS_CORNER::MIN] ) && !isNumberNA( value[IBIS_CORNER::MIN] ) )
149 status = false;
150 if( std::isnan( value[IBIS_CORNER::MAX] ) && !isNumberNA( value[IBIS_CORNER::MAX] ) )
151 status = false;
152
153 return status;
154}
155
157{
158 bool status = true;
159
160 if( !m_Rpkg.Check() )
161 {
162 Report( _( "Invalid R_pkg value." ), RPT_SEVERITY_ERROR );
163 status = false;
164 }
165 if( !m_Lpkg.Check() )
166 {
167 Report( _( "Invalid L_pkg value." ), RPT_SEVERITY_ERROR );
168 status = false;
169 }
170 if( !m_Cpkg.Check() )
171 {
172 Report( _( "Invalid C_pkg value." ), RPT_SEVERITY_ERROR );
173 status = false;
174 }
175
176 return status;
177}
178
180{
181 bool status = true;
182
183 if( !m_dummy )
184 {
185 std::stringstream message;
186 message << _( "Checking pin " ) << m_pinName;
187
188 if( m_pinName.empty() )
189 {
190 if(status )
191 Report( message.str(), RPT_SEVERITY_ACTION );
192
193 Report( _( "Pin name cannot be empty." ), RPT_SEVERITY_ERROR );
194 status = false;
195 }
196 if( m_signalName.empty() )
197 {
198 if(status )
199 Report( message.str(), RPT_SEVERITY_ACTION );
200
201 Report( _( "Signal name cannot be empty." ), RPT_SEVERITY_ERROR );
202 status = false;
203 }
204 if( m_modelName.empty() )
205 {
206 if(status )
207 Report( message.str(), RPT_SEVERITY_ACTION );
208
209 Report( _( "Model name cannot be empty." ), RPT_SEVERITY_ERROR );
210 status = false;
211 }
212 if( std::isnan( m_Rpin ) && !isNumberNA( m_Rpin ) )
213 {
214 if(status )
215 Report( message.str(), RPT_SEVERITY_ACTION );
216
217 Report( _( "Rpin is not valid." ), RPT_SEVERITY_ERROR );
218 status = false;
219 }
220 if( std::isnan( m_Lpin )&& !isNumberNA( m_Lpin ) )
221 {
222 if(status )
223 Report( message.str(), RPT_SEVERITY_ACTION );
224
225 Report( _( "Lpin is not valid." ), RPT_SEVERITY_ERROR );
226 status = false;
227 }
228 if( std::isnan( m_Cpin )&& !isNumberNA( m_Cpin ) )
229 {
230 if(status )
231 Report( message.str(), RPT_SEVERITY_ACTION );
232
233 Report( _( "Cpin is not valid." ), RPT_SEVERITY_ERROR );
234 status = false;
235 }
236 }
237
238 return status;
239}
240
241
243{
244 bool status = true;
245
246 std::stringstream message;
247 message << _( "Checking component " ) << m_name;
248
249 if( m_name.empty() )
250 {
251 if( status )
252 Report( message.str(), RPT_SEVERITY_ACTION );
253
254 Report( _( "Component: name cannot be empty." ), RPT_SEVERITY_ERROR );
255 status = false;
256 }
257
258 if( m_manufacturer.empty() )
259 {
260 if( status )
261 Report( message.str(), RPT_SEVERITY_ACTION );
262
263 Report( _( "Component: manufacturer cannot be empty." ), RPT_SEVERITY_ERROR );
264 status = false;
265 }
266
267 if( !m_package.Check() )
268 {
269 if( status )
270 Report( message.str(), RPT_SEVERITY_ACTION );
271
272 Report( _( "Component: invalid package." ), RPT_SEVERITY_ERROR );
273 status = false;
274 }
275
276 if( m_pins.size() < 1 )
277 {
278 if( status )
279 Report( message.str(), RPT_SEVERITY_ACTION );
280
281 Report( _( "Component: no pin" ), RPT_SEVERITY_ERROR );
282 status = false;
283 }
284
285 for( IbisComponentPin& pin : m_pins )
286 {
287 status &= pin.Check();
288 }
289
290 return status;
291}
292
293
295{
296 return true;
297}
298
299
300std::string IBIS_ANY::doubleToString( double aNumber )
301{
302 std::ostringstream ss;
303 ss.setf( std::ios_base::scientific, std::ios_base::floatfield );
304 ss << aNumber;
305 return ss.str();
306}
307
308
309std::string IVtable::Spice( int aN, const std::string& aPort1, const std::string& aPort2,
310 const std::string& aModelName, IBIS_CORNER aCorner ) const
311{
312 std::string result = "";
313
314 if( m_entries.size() > 0 )
315 {
316 result += "a";
317 result += std::to_string( aN );
318 result += " %vd(";
319 result += aPort1;
320 result += " ";
321 result += aPort2;
322 result += ") %id(";
323 result += aPort1;
324 result += " ";
325 result += aPort2;
326 result += ") ";
327 result += aModelName;
328 result += "\n";
329 result += "\n";
330 result += ".model ";
331 result += aModelName;
332 result += " pwl(\n+ x_array=[";
333
334 for( const IVtableEntry& entry : m_entries )
335 {
336 result += doubleToString( entry.V );
337 result += "\n+";
338 }
339 result += "]\n+ y_array=[";
340
341 for( const IVtableEntry& entry : m_entries )
342 {
343 result += doubleToString( entry.I.value[aCorner] );
344 result += "\n+";
345 }
346 result += "]\n+ input_domain=0.05 fraction=TRUE)\n\n";
347 }
348 return result;
349}
350
351double IVtable::InterpolatedI( double aV, IBIS_CORNER aCorner ) const
352{
353 // @TODO change this algorithm
354
355 if( m_entries.back().V > m_entries.at( 0 ).V )
356 {
357 if( aV >= m_entries.back().V )
358 {
359 return m_entries.back().I.value[aCorner];
360 }
361
362 if( aV <= m_entries.at( 0 ).V )
363 {
364 return m_entries.at( 0 ).I.value[aCorner];
365 }
366
367 for( size_t i = 1; i < m_entries.size(); i++ )
368 {
369 if( m_entries.at( i ).V > aV )
370 {
371 return m_entries.at( i - 1 ).I.value[aCorner]
372 + ( m_entries.at( i ).I.value[aCorner]
373 - m_entries.at( i - 1 ).I.value[aCorner] )
374 / ( m_entries.at( i ).V - m_entries.at( i - 1 ).V )
375 * ( aV - m_entries.at( i - 1 ).V );
376 }
377 }
378 Report( _( "Cannot interpolate the current based on this IV table." ), RPT_SEVERITY_ERROR );
379 return nan( "" );
380 }
381 else
382 {
383 // exiting the function here would mean the IV table is reversed.
384 return nan( "" );
385 }
386 // @TODO prefer another method such as a dichotomy
387}
388
390{
391 bool status = true;
392 for( IVtableEntry& entry : m_entries )
393 {
394 if( std::isnan( entry.V ) )
395 {
396 Report( _( "There is an invalid voltage in an IV table" ), RPT_SEVERITY_ERROR );
397 status = false;
398 break;
399 }
400
401 if( !entry.I.Check() )
402 {
403 Report( _( "There is an invalid current in an IV table" ), RPT_SEVERITY_ERROR );
404 status = false;
405 break;
406 }
407 }
408 // TODO: Check if the IV table is monotonic :
409 // IBIS standard defines 8 criteria for an IV table to be monotonic
410 // Issue a warning, not an error
411
412 return status;
413}
414
415
417{
418 bool status = true;
419
420 if( std::isnan( value[IBIS_CORNER::TYP].m_dv ) )
421 status = false;
422 if( std::isnan( value[IBIS_CORNER::TYP].m_dt ) )
423 status = false;
424
425
426 if( std::isnan( value[IBIS_CORNER::MIN].m_dv ) && !isNumberNA( value[IBIS_CORNER::MIN].m_dv ) )
427 status = false;
428 if( std::isnan( value[IBIS_CORNER::MIN].m_dt ) && !isNumberNA( value[IBIS_CORNER::MIN].m_dt ) )
429 status = false;
430
431 if( std::isnan( value[IBIS_CORNER::MIN].m_dv ) && !isNumberNA( value[IBIS_CORNER::MIN].m_dv ) )
432 status = false;
433 if( std::isnan( value[IBIS_CORNER::MIN].m_dt ) && !isNumberNA( value[IBIS_CORNER::MIN].m_dt ) )
434 status = false;
435
436 return status;
437}
438
440{
441 bool status = true;
442
443 if( std::isnan( m_Rload ) )
444 {
445 status = false;
446 Report( _( "Invalid R_load." ), RPT_SEVERITY_ERROR );
447 }
448 if( !m_falling.Check() )
449 {
450 Report( _( "Invalid falling dV/dt." ), RPT_SEVERITY_ERROR );
451 status = false;
452 }
453 if( !m_rising.Check() )
454 {
455 Report( _( "Invalid rising dV/dt." ), RPT_SEVERITY_ERROR );
456 status = false;
457 }
458
459 return status;
460}
461
462
463
465{
466 bool status = true;
467
468 if( m_name.empty() )
469 {
470 Report( _( "Model name cannot be empty" ), RPT_SEVERITY_ERROR );
471 status = false;
472 }
473
474 std::stringstream message;
475 message << _( "Checking model " ) << m_name;
476
477 if(m_type == IBIS_MODEL_TYPE::UNDEFINED)
478 {
479 if( status )
480 Report( message.str(), RPT_SEVERITY_ACTION );
481
482 Report( _( "Undefined model type." ), RPT_SEVERITY_ERROR );
483 status = false;
484 }
485
486 if( std::isnan( m_vinh ) && !isNumberNA( m_vinh ) )
487 {
488 if( status )
489 Report( message.str(), RPT_SEVERITY_ACTION );
490
491 Report( _( "Invalid Vinh value." ), RPT_SEVERITY_ERROR );
492 status = false;
493 }
494 if( std::isnan( m_vinl ) && !isNumberNA( m_vinl ) )
495 {
496 if( status )
497 Report( message.str(), RPT_SEVERITY_ACTION );
498
499 Report( _( "Invalid Vinl value." ), RPT_SEVERITY_ERROR );
500 status = false;
501 }
502 if( std::isnan( m_rref ) && !isNumberNA( m_rref ) )
503 {
504 if( status )
505 Report( message.str(), RPT_SEVERITY_ACTION );
506
507 Report( _( "Invalid R_ref value." ), RPT_SEVERITY_ERROR );
508 status = false;
509 }
510 if( std::isnan( m_cref ) && !isNumberNA( m_cref ) )
511 {
512 if( status )
513 Report( message.str(), RPT_SEVERITY_ACTION );
514
515 Report( _( "Invalid C_ref value." ), RPT_SEVERITY_ERROR );
516 status = false;
517 }
518 if( std::isnan( m_vref ) && !isNumberNA( m_vref ) )
519 {
520 if( status )
521 Report( message.str(), RPT_SEVERITY_ACTION );
522
523 Report( _( "Invalid V_ref value." ), RPT_SEVERITY_ERROR );
524 status = false;
525 }
526 if( std::isnan( m_vmeas ) && !isNumberNA( m_vmeas ) )
527 {
528 if( status )
529 Report( message.str(), RPT_SEVERITY_ACTION );
530
531 Report( _( "Invalid V_meas value." ), RPT_SEVERITY_ERROR );
532 status = false;
533 }
534 if( !m_C_comp.Check() )
535 {
536 if( status )
537 Report( message.str(), RPT_SEVERITY_ACTION );
538
539 Report( _( "C_comp is invalid." ), RPT_SEVERITY_ERROR );
540 status = false;
541 }
543 {
544 if( status )
545 Report( message.str(), RPT_SEVERITY_ACTION );
546
547 Report( _( "Temperature Range is invalid." ), RPT_SEVERITY_ERROR );
548 status = false;
549 }
550
551 if( !m_voltageRange.Check() )
552 {
553 // If the voltage range is not valid, it's ok, only if we have pulls and clamps
555 {
556 status = false;
557 }
558 if( !m_pullupReference.Check() )
559 {
560 status = false;
561 }
563 {
564 status = false;
565 }
567 {
568 status = false;
569 }
570 if( !status )
571 {
572 Report( _( "Voltage Range is invalid." ), RPT_SEVERITY_ERROR );
573 }
574 status = false;
575 }
576 if( !m_pulldown.Check() )
577 {
578 Report( _( "Invalid pulldown." ), RPT_SEVERITY_ERROR );
579 status = false;
580 }
581 if( !m_pullup.Check() )
582 {
583 Report( _( "Invalid pullup." ), RPT_SEVERITY_ERROR );
584 status = false;
585 }
586 if( !m_POWERClamp.Check() )
587 {
588 Report( _( "Invalid POWER clamp." ), RPT_SEVERITY_ERROR );
589 status = false;
590 }
591 if( !m_GNDClamp.Check() )
592 {
593 Report( _( "Invalid GND clamp." ), RPT_SEVERITY_ERROR );
594 status = false;
595 }
596 if( m_type != IBIS_MODEL_TYPE::INPUT_ECL && m_type != IBIS_MODEL_TYPE::INPUT_STD
597 && m_type != IBIS_MODEL_TYPE::TERMINATOR && m_type != IBIS_MODEL_TYPE::SERIES
598 && m_type != IBIS_MODEL_TYPE::SERIES_SWITCH )
599 {
600 if( !m_ramp.Check() )
601 {
602 Report( _( "Invalid Ramp" ), RPT_SEVERITY_ERROR );
603 }
604 }
605 return status;
606}
607
609{
610 bool status = true;
611
612 std::stringstream message;
613 message << _( "Checking Header..." );
614
615 if( m_ibisVersion == -1 )
616 {
617 if(status )
618 Report( message.str(), RPT_SEVERITY_ACTION );
619
620 Report( _( "Missing [IBIS Ver]" ), RPT_SEVERITY_ERROR );
621 status = false;
622 }
623
625 {
626 if(status )
627 Report( message.str(), RPT_SEVERITY_ACTION );
628
629 Report( _( "The parser does not handle this IBIS version" ), RPT_SEVERITY_ERROR );
630 status = false;
631 }
632
633 if( m_fileRevision == -1 )
634 {
635 if(status )
636 Report( message.str(), RPT_SEVERITY_ACTION );
637
638 Report( _( "Missing [File Rev]" ), RPT_SEVERITY_ERROR );
639 status = false;
640 }
641
642 if( m_fileName.empty() )
643 {
644 if(status )
645 Report( message.str(), RPT_SEVERITY_ACTION );
646
647 Report( _( "Missing [File Name]" ), RPT_SEVERITY_ERROR );
648 status = false;
649 }
650
651 std::string ext = m_fileName.substr( m_fileName.length() - 4 );
652
653 if( !( !strcmp( ext.c_str(), ".ibs" ) || !strcmp( ext.c_str(), ".pkg" )
654 || !strcmp( ext.c_str(), ".ebd" ) || !strcmp( ext.c_str(), ".ims" ) ) )
655 {
656 if(status )
657 Report( message.str(), RPT_SEVERITY_ACTION );
658
659 Report( "Invalid file extension in [File Name]", RPT_SEVERITY_ERROR );
660 status = false;
661 }
662
663
664 return status;
665}
666
668{
669 bool status = true;
670
671 if( m_name.empty() )
672 {
673 Report( _( "Package model name cannot be empty." ), RPT_SEVERITY_ERROR );
674 status = false;
675 }
676
677 std::stringstream message;
678 message << _( "Checking package model " ) << m_name;
679
680 if( m_manufacturer.empty() )
681 {
682 if( status )
683 Report( message.str(), RPT_SEVERITY_ACTION );
684
685 Report( _( "Manufacturer cannot be empty." ), RPT_SEVERITY_ERROR );
686 status = false;
687 }
688
689 if( m_OEM.empty() )
690 {
691 if( status )
692 Report( message.str(), RPT_SEVERITY_ACTION );
693
694 Report( _( "OEM cannot be empty." ), RPT_SEVERITY_ERROR );
695 status = false;
696 }
697
698 if( m_numberOfPins < 0 )
699 {
700 if( status )
701 Report( message.str(), RPT_SEVERITY_ACTION );
702
703 Report( _( "Negative number of pins." ), RPT_SEVERITY_ERROR );
704 status = false;
705 }
706
707 if( (int)m_pins.size() != m_numberOfPins )
708 {
709 if( status )
710 Report( message.str(), RPT_SEVERITY_ACTION );
711
712 Report( "Number of pins does not match [Pin Numbers] size.", RPT_SEVERITY_ERROR );
713 status = false;
714 }
715
716 for( size_t i = 0; i < m_pins.size(); i++ )
717 {
718 if( m_pins.at( i ).empty() )
719 {
720 if( status )
721 Report( message.str(), RPT_SEVERITY_ACTION );
722
723 Report( _( "Empty pin number." ), RPT_SEVERITY_ERROR );
724 status = false;
725 }
726 }
727 // resistance matrix is not required
728
729 if( !( m_resistanceMatrix )->Check() )
730 {
731 if( status )
732 Report( message.str(), RPT_SEVERITY_ACTION );
733
734 Report( _( "Resistance matrix is incorrect." ), RPT_SEVERITY_ERROR );
735 status = false;
736 }
737
738 if( m_capacitanceMatrix != nullptr )
739 {
740 if( m_capacitanceMatrix->m_type == IBIS_MATRIX_TYPE::UNDEFINED )
741 {
742 if( status )
743 Report( message.str(), RPT_SEVERITY_ACTION );
744
745 Report( _( "Capacitance matrix is undefined." ), RPT_SEVERITY_ERROR );
746 status = false;
747 }
748
749 if( !m_capacitanceMatrix->Check() )
750 {
751 if( status )
752 Report( message.str(), RPT_SEVERITY_ACTION );
753
754 Report( _( "Capacitance matrix is incorrect." ), RPT_SEVERITY_ERROR );
755 status = false;
756 }
757 }
758 else
759 {
760 if( status )
761 Report( message.str(), RPT_SEVERITY_ACTION );
762
763 Report( _( "Capacitance matrix is nullptr." ), RPT_SEVERITY_ERROR );
764 status = false;
765 }
766
767 if( m_inductanceMatrix != nullptr )
768 {
769 if( m_inductanceMatrix->m_type == IBIS_MATRIX_TYPE::UNDEFINED )
770 {
771 if( status )
772 Report( message.str(), RPT_SEVERITY_ACTION );
773
774 Report( _( "Inductance matrix is undefined." ), RPT_SEVERITY_ERROR );
775 status = false;
776 }
777
778 if( !m_inductanceMatrix->Check() )
779 {
780 if( status )
781 Report( message.str(), RPT_SEVERITY_ACTION );
782
783 Report( _( "Inductance matrix is incorrect." ), RPT_SEVERITY_ERROR );
784 status = false;
785 }
786 }
787 else
788 {
789 if( status )
790 Report( message.str(), RPT_SEVERITY_ACTION );
791
792 Report( _( "Inductance matrix is nullptr." ), RPT_SEVERITY_ERROR );
793 status = false;
794 }
795 return status;
796}
797
798
799bool IbisParser::ParseFile( const std::string& aFileName )
800{
801 std::stringstream err_msg;
802
803 std::ifstream ibisFile;
804 ibisFile.open( aFileName );
805
806 if( !ibisFile.is_open() )
807 {
808 err_msg << _( "Cannot open file " ) << aFileName;
809 Report( err_msg.str(), RPT_SEVERITY_ERROR );
810 return false;
811 }
812
813 std::ostringstream ss;
814 ss << ibisFile.rdbuf();
815 const std::string& s = ss.str();
816 m_buffer = std::vector<char>( s.begin(), s.end() );
817 m_buffer.push_back( 0 );
818
819 long size = m_buffer.size();
820
821 m_lineCounter = 0;
822 m_bufferIndex = 0;
823
824 bool status = true;
825
826 LOCALE_IO toggle; // Temporary switch the locale to standard C to r/w floats
827
828 while( ( m_bufferIndex < size ) && status )
829 {
830 if( !getNextLine() )
831 {
832 Report( _( "Unexpected end of file. Missing [END] ?" ), RPT_SEVERITY_ERROR );
833 status = false;
834 }
835
836 if( status && m_parrot )
837 {
838 printLine();
839 }
840
841 if( status && !onNewLine() )
842 {
843 err_msg.clear();
844 err_msg << _( "Error on line " ) << std::to_string( m_lineCounter );
845 Report( err_msg.str(), RPT_SEVERITY_ERROR );
846 status = false;
847 }
848 if( m_context == IBIS_PARSER_CONTEXT::END )
849 {
850 break;
851 }
852 }
853
854 m_buffer.clear();
855 return status;
856}
857
859{
860 while( ( isspace( m_buffer[m_lineOffset + m_lineIndex] ) ) && ( m_lineIndex < m_lineLength ) )
861 {
862 m_lineIndex++;
863 }
864}
865
867{
869
871 {
872 Report( _( "A line did not end properly." ), RPT_SEVERITY_ERROR );
873 return false;
874 }
875 return true;
876}
877
878
880{
881 int cursor = m_lineIndex;
882
883 while( ( isspace( m_buffer[m_lineOffset + cursor] ) ) && ( cursor < m_lineLength ) )
884 {
885 cursor++;
886 }
887
888 return ( cursor >= m_lineLength );
889}
890
891bool IbisParser::readDvdt( std::string& aString, dvdt& aDest )
892{
893 bool status = true;
894
895 if( aString == "NA" )
896 {
897 aDest.m_dv = nan( NAN_NA );
898 aDest.m_dt = nan( NAN_NA );
899
900 return status;
901 }
902
903 int i = 0;
904
905 for( i = 1; i < (int)aString.length(); i++ )
906 {
907 if( aString.at( i ) == '/' )
908 {
909 break;
910 }
911 }
912
913 if( aString.at( i ) == '/' )
914 {
915 std::string str1 = aString.substr( 0, i );
916 std::string str2 = aString.substr( i + 1, aString.size() - i - 1 );
917
918 if( !parseDouble( aDest.m_dv, str1, true ) || !parseDouble( aDest.m_dt, str2, true ) )
919 {
920 status = false;
921 }
922 }
923
924 return status;
925}
926
927
928bool IbisParser::parseDouble( double& aDest, std::string& aStr, bool aAllowModifiers )
929{
930 // " an entry of the C matrix could be given as 1.23e-12 or as 1.23p or 1.23pF."
931 // Kibis: This implementation will also allow 1.23e-3n
932
934 bool status = true;
935 bool converted = false;
936
937 std::string str = aStr;
938
939 double result;
940 size_t size = 0;
941
942
943 if( str == "NA" )
944 {
945 result = nan( NAN_NA );
946 }
947 else
948 {
949 try
950 {
951 result = std::stod( str, &size );
952 converted = true;
953 }
954 catch( ... )
955 {
956 result = nan( NAN_INVALID );
957 status = false;
958 }
959 }
960
961 if( converted && ( size < str.length() ) )
962 {
963 switch( static_cast<char>( str.at( size ) ) )
964 {
965 case 'T': result *= 1e12; break;
966 case 'G': result *= 1e9; break;
967 case 'M': result *= 1e6; break;
968 case 'k': result *= 1e3; break;
969 case 'm': result *= 1e-3; break;
970 case 'u': result *= 1e-6; break;
971 case 'n': result *= 1e-9; break;
972 case 'p': result *= 1e-12; break;
973 case 'f': result *= 1e-15; break;
974 default:
975 break;
976 // In some files, "vinh = 3.0V", therefore we can't return false in the default case
977 }
978 }
979
980 aDest = result;
981
982 return status;
983}
984
985
987{
989
990 long tmpIndex = m_bufferIndex;
991
993
994 if( m_bufferIndex >= (int)m_buffer.size() )
995 return false;
996
997 char c = m_buffer[m_bufferIndex++];
998
999 int i = 1;
1000 while( c != m_commentChar && c != 0 && c != '\n' && i < IBIS_MAX_LINE_LENGTH )
1001 {
1002 c = m_buffer[m_bufferIndex++];
1003 i++;
1004 }
1005
1006 if( i == IBIS_MAX_LINE_LENGTH )
1007 {
1008 Report( _( "Line exceeds maximum length." ), RPT_SEVERITY_ERROR );
1009 return false;
1010 }
1011
1012 m_lineLength = m_bufferIndex - tmpIndex - 1; // Don't add the end of line condition
1013 m_lineIndex = 0;
1014
1015 if( c == m_commentChar )
1016 {
1017 while( c != 0 && c != '\n' )
1018 {
1019 c = m_buffer[m_bufferIndex++];
1020 }
1021 }
1022
1023 if( i == IBIS_MAX_LINE_LENGTH )
1024 {
1025 Report( _( "Line exceeds maximum length." ), RPT_SEVERITY_ERROR );
1026 return false;
1027 }
1028
1029 return true;
1030}
1031
1032
1034{
1035 for( int i = 0; i < m_lineLength; i++ )
1036 {
1037 std::cout << m_buffer[m_lineOffset + i];
1038 }
1039 std::cout << std::endl;
1040}
1041
1042bool IbisParser::readDouble( double& aDest )
1043{
1044 bool status = true;
1045 std::string str;
1046
1047 if( readWord( str ) )
1048 {
1049 if( !parseDouble( aDest, str, true ) )
1050 {
1051 Report( _( "Failed to read a double." ), RPT_SEVERITY_WARNING );
1052 status = false;
1053 }
1054 }
1055 else
1056 {
1057 Report( _( "Failed to read a word." ), RPT_SEVERITY_WARNING );
1058 status = false;
1059 }
1060
1061 return status;
1062}
1063
1064bool IbisParser::readInt( int& aDest )
1065{
1066 bool status = true;
1067 std::string str;
1068
1069 if( readWord( str ) )
1070 {
1071 double result;
1072 size_t size = 0;
1073
1074 try
1075 {
1076 result = std::stoi( str, &size );
1077 }
1078 catch( ... )
1079 {
1080 if( str == "NA" )
1081 {
1082 result = nan( NAN_NA );
1083 }
1084 else
1085 {
1086 result = nan( NAN_INVALID );
1087 status = false;
1088 }
1089 }
1090
1091 if( size != str.size() )
1092 {
1093 status = false;
1094 Report( _( "Number is not an integer" ), RPT_SEVERITY_WARNING );
1095 }
1096
1097 aDest = result;
1098 }
1099 else
1100 {
1101 Report( _( "Failed to read a word." ), RPT_SEVERITY_WARNING );
1102 status = false;
1103 }
1104
1105 return status;
1106}
1107
1108bool IbisParser::readWord( std::string& aDest )
1109{
1111
1112 int startIndex = m_lineIndex;
1113
1114 while( ( !isspace( m_buffer[m_lineOffset + m_lineIndex] ) ) && ( m_lineIndex < m_lineLength ) )
1115 {
1116 m_lineIndex++;
1117 }
1118
1119 std::vector<char>::iterator start = std::next( m_buffer.begin(), m_lineOffset + startIndex );
1120 std::vector<char>::iterator end = std::next( m_buffer.begin(), m_lineOffset + m_lineIndex );
1121 aDest = std::string( start, end );
1122
1123 return ( aDest.size() > 0 );
1124}
1125
1126bool IbisParser::readString( std::string& aDest )
1127{
1128 while( m_lineIndex < m_lineLength )
1129 {
1130 aDest += m_buffer[m_lineOffset + m_lineIndex++];
1131 }
1132
1133 // Remove extra whitespace characters
1134 int len = aDest.length();
1135
1136 if( len < 1 )
1137 {
1138 // The data is likely on the next line. Skip.
1139 return true;
1140 }
1141
1142 char c = aDest[len - 1];
1143 int i = 0;
1144
1145 while( isspace( c ) && ( i < len ) )
1146 {
1147 c = aDest[len - 1 - i];
1148 i++;
1149 }
1150 aDest = aDest.substr( 0, len - i + 1 );
1151
1152 return true;
1153}
1154
1155bool IbisParser::storeString( std::string& aDest, bool aMultiline )
1156{
1157 bool status = true;
1158
1160
1161 status &= readString( aDest );
1162
1163 m_continue = aMultiline ? IBIS_PARSER_CONTINUE::STRING : IBIS_PARSER_CONTINUE::NONE;
1164 m_continuingString = &aDest;
1165
1166 status &= checkEndofLine();
1167 return status;
1168}
1169
1170
1172{
1174
1175 std::string strChar = "";
1176
1177 // We cannot stop at m_lineLength here, because lineLength could stop before |_char
1178 // if the char remains the same
1179
1180 char c = m_buffer[m_lineOffset + m_lineIndex++];
1181 char d = c;
1182
1183 if( !( c == '!' || c == '"' || c == '#' || c == '$' || c == '%' || c == '&' || c == '\''
1184 || c == '(' || c == ')' || c == '*' || c == ',' || c == ':' || c == ';' || c == '<'
1185 || c == '>' || c == '?' || c == '@' || c == '\\' || c == '^' || c == '`' || c == '{'
1186 || c == '|' || c == '}' || c == '~' || c == ')' ) )
1187 {
1188 Report( _( "New comment character is invalid." ), RPT_SEVERITY_ERROR );
1189 }
1190
1192
1193 while( ( !isspace( c ) ) && c != 0 && c != '\n' )
1194 {
1195 strChar += c;
1197 }
1198
1199 if( strChar != "_char" )
1200 {
1201 Report( _( "Invalid syntax. Should be |_char or &_char, etc..." ), RPT_SEVERITY_ERROR );
1202 return false;
1203 }
1204
1205 while( isspace( c ) && c != 0 && c != '\n' && c != d )
1206 {
1208 }
1209
1210 if( ( !isspace( c ) ) && c != d )
1211 {
1212 Report( _( "No extra argument was expected" ), RPT_SEVERITY_ERROR );
1213 return false;
1214 }
1215
1216 m_commentChar = d;
1217
1218
1219 m_continue = IBIS_PARSER_CONTINUE::NONE;
1220
1221 return true;
1222}
1223
1225{
1226 std::string keyword = "";
1227 //"Keywords must be enclosed in square brackets, “[]”, and must start in column 1 of the line."
1228 //"No space or tab is allowed immediately after the opening bracket “[” or immediately"
1229 // "before the closing bracket “]"
1230
1231 if( m_buffer[m_lineOffset + m_lineIndex] != '[' )
1232 {
1233 // We return an empty keyword, this should stop the parser.
1234 return "";
1235 }
1236
1237 m_lineIndex++;
1238
1239 char c;
1241
1242 while( ( c != ']' )
1243 && ( m_lineIndex
1244 < m_lineLength ) ) // We know the maximum keyword length, we could add a condition.
1245 {
1246 // "Underscores and spaces are equivalent in keywords"
1247 if( c == ' ' )
1248 {
1249 c = '_';
1250 }
1251 keyword += c;
1253 }
1254
1255 return keyword;
1256}
1257
1258bool IbisParser::changeContext( std::string& aKeyword )
1259{
1260 bool status = true;
1261
1262 if( status )
1263 {
1264 switch( m_context )
1265 {
1266 case IBIS_PARSER_CONTEXT::HEADER: status &= m_ibisFile.m_header.Check(); break;
1267 case IBIS_PARSER_CONTEXT::COMPONENT: status &= m_currentComponent->Check(); break;
1268 case IBIS_PARSER_CONTEXT::MODEL: status &= m_currentModel->Check(); break;
1269 case IBIS_PARSER_CONTEXT::MODELSELECTOR: status &= m_currentModelSelector->Check(); break;
1270 case IBIS_PARSER_CONTEXT::PACKAGEMODEL: status &= m_currentPackageModel->Check(); break;
1271 case IBIS_PARSER_CONTEXT::END:
1272 Report( "Cannot change context after [END]" );
1273 status = false;
1274 break;
1275
1276 default: Report( "Changing context from an undefined context" );
1277 }
1278 }
1279
1280 if( !compareIbisWord( aKeyword.c_str(), "End" ) && status )
1281 {
1282 //New context
1283 if( compareIbisWord( aKeyword.c_str(), "Component" ) )
1284 {
1287 status &= storeString( m_currentComponent->m_name, false );
1288 m_context = IBIS_PARSER_CONTEXT::COMPONENT;
1289 }
1290 else if( compareIbisWord( aKeyword.c_str(), "Model_Selector" ) )
1291 {
1293 status &= storeString( MS.m_name, false );
1294 m_ibisFile.m_modelSelectors.push_back( MS );
1296 m_context = IBIS_PARSER_CONTEXT::MODELSELECTOR;
1297 m_continue = IBIS_PARSER_CONTINUE::MODELSELECTOR;
1298 }
1299 else if( compareIbisWord( aKeyword.c_str(), "Model" ) )
1300 {
1301 IbisModel model( m_reporter );
1302 model.m_temperatureRange.value[IBIS_CORNER::MIN] = 0;
1303 model.m_temperatureRange.value[IBIS_CORNER::TYP] = 50;
1304 model.m_temperatureRange.value[IBIS_CORNER::MAX] = 100;
1305 status &= storeString( model.m_name, false );
1306 m_ibisFile.m_models.push_back( model );
1307 m_currentModel = &( m_ibisFile.m_models.back() );
1308 m_context = IBIS_PARSER_CONTEXT::MODEL;
1309 m_continue = IBIS_PARSER_CONTINUE::MODEL;
1310 }
1311 else if( compareIbisWord( aKeyword.c_str(), "Define_Package_Model" ) )
1312 {
1314 PM.m_resistanceMatrix = std::unique_ptr<IBIS_MATRIX>( new IBIS_MATRIX( m_reporter ) );
1315 PM.m_capacitanceMatrix = std::unique_ptr<IBIS_MATRIX>( new IBIS_MATRIX( m_reporter ) );
1316 PM.m_inductanceMatrix = std::unique_ptr<IBIS_MATRIX>( new IBIS_MATRIX( m_reporter ) );
1317
1318 PM.m_resistanceMatrix->m_type = IBIS_MATRIX_TYPE::UNDEFINED;
1319 PM.m_capacitanceMatrix->m_type = IBIS_MATRIX_TYPE::UNDEFINED;
1320 PM.m_inductanceMatrix->m_type = IBIS_MATRIX_TYPE::UNDEFINED;
1321
1322 PM.m_resistanceMatrix->m_dim = -1;
1323 PM.m_capacitanceMatrix->m_dim = -1;
1324 PM.m_inductanceMatrix->m_dim = -1;
1325
1326 status &= storeString( PM.m_name, false );
1327
1328 m_ibisFile.m_packageModels.push_back( PM );
1330 m_context = IBIS_PARSER_CONTEXT::PACKAGEMODEL;
1331 }
1332 else if( compareIbisWord( aKeyword.c_str(), "End_Package_Model" ) )
1333 {
1334 if( m_currentComponent != nullptr )
1335 {
1336 m_context = IBIS_PARSER_CONTEXT::COMPONENT;
1337 m_continue = IBIS_PARSER_CONTINUE::NONE;
1338 }
1339 else // .pkg file, we just go back to header, to get the [END] keyword
1340 { // This will cause the header to be checked twice.
1341 m_context = IBIS_PARSER_CONTEXT::HEADER;
1342 m_continue = IBIS_PARSER_CONTINUE::NONE;
1343 }
1344 }
1345 else
1346 {
1347 status = false;
1348 std::string context_string;
1349
1350 switch( m_context )
1351 {
1352 case IBIS_PARSER_CONTEXT::HEADER: context_string += "HEADER"; break;
1353 case IBIS_PARSER_CONTEXT::COMPONENT: context_string += "COMPONENT"; break;
1354 case IBIS_PARSER_CONTEXT::MODELSELECTOR: context_string += "MODEL_SELECTOR"; break;
1355 case IBIS_PARSER_CONTEXT::MODEL: context_string += "MODEL"; break;
1356 case IBIS_PARSER_CONTEXT::PACKAGEMODEL: context_string += "PACKAGE_MODEL"; break;
1357 case IBIS_PARSER_CONTEXT::PACKAGEMODEL_MODELDATA:
1358 context_string += "PACKAGE_MODEL_MODEL_DATA";
1359 break;
1360 default: context_string += "???"; break;
1361 }
1362
1363 std::stringstream message;
1364 message << _( "Unknown keyword in " ) << context_string << _( " context: " ) << aKeyword;
1365 Report( message.str(), RPT_SEVERITY_ERROR );
1366 }
1367 }
1368 else
1369 {
1370 m_context = IBIS_PARSER_CONTEXT::END;
1371 }
1372
1373 return status;
1374}
1375
1376
1377bool IbisParser::parseModelSelector( std::string& aKeyword )
1378{
1379 bool status = true;
1380
1381 if( !changeContext( aKeyword ) )
1382 {
1383 status = false;
1384 }
1385 return status;
1386}
1387
1388
1390{
1391 bool status = true;
1392 std::string str;
1393
1394 if( readWord( str ) )
1395 {
1396 status &= readDvdt( str, aDest.value[IBIS_CORNER::TYP] )
1397 && readDvdt( str, aDest.value[IBIS_CORNER::MIN] )
1398 && readDvdt( str, aDest.value[IBIS_CORNER::MAX] );
1399 }
1400 else
1401 {
1402 status = false;
1403 }
1404
1405 return status;
1406}
1407
1409{
1410 bool status = true;
1411
1412 m_continue = IBIS_PARSER_CONTINUE::RAMP;
1413
1414 if( !readNumericSubparam( std::string( "R_load" ), m_currentModel->m_ramp.m_Rload ) )
1415 {
1416 std::string str;
1417
1418 if( readWord( str ) )
1419 {
1420 if( !strcmp( str.c_str(), "dV/dt_r" ) )
1421 {
1423 }
1424 else if( !strcmp( str.c_str(), "dV/dt_f" ) )
1425 {
1427 }
1428 else
1429 {
1430 Report( _( "Invalid ramp data" ), RPT_SEVERITY_ERROR );
1431 status = false;
1432 }
1433 }
1434 }
1435 return status;
1436}
1437
1438
1440{
1441 bool status = true;
1442
1443 m_continue = IBIS_PARSER_CONTINUE::MODEL_SPEC;
1444
1445 // TODO
1446 // readTypMinMaxValueSubparam( std::string( "Vmeas" ), m_currentModel->... )
1447 // ...
1448
1449 return status;
1450}
1451
1452
1453bool IbisParser::parseModel( std::string& aKeyword )
1454{
1455 bool status = false;
1456
1457 if( compareIbisWord( aKeyword.c_str(), "Voltage_Range" ) )
1459 else if( compareIbisWord( aKeyword.c_str(), "Temperature_Range" ) )
1461 else if( compareIbisWord( aKeyword.c_str(), "GND_Clamp" ) )
1463 else if( compareIbisWord( aKeyword.c_str(), "POWER_Clamp" ) )
1465 else if( compareIbisWord( aKeyword.c_str(), "Pulldown" ) )
1467 else if( compareIbisWord( aKeyword.c_str(), "Pullup" ) )
1469 else if( compareIbisWord( aKeyword.c_str(), "Rising_Waveform" ) )
1470 status = readWaveform( nullptr, IBIS_WAVEFORM_TYPE::RISING );
1471 else if( compareIbisWord( aKeyword.c_str(), "Falling_Waveform" ) )
1472 status = readWaveform( nullptr, IBIS_WAVEFORM_TYPE::FALLING );
1473 else if( compareIbisWord( aKeyword.c_str(), "Ramp" ) )
1474 status = readRamp();
1475 else if( compareIbisWord( aKeyword.c_str(), "Model_Spec" ) )
1476 status = readModelSpec();
1477 else if( compareIbisWord( aKeyword.c_str(), "Pullup_Reference" ) )
1479 else if( compareIbisWord( aKeyword.c_str(), "Pulldown_Reference" ) )
1481 else if( compareIbisWord( aKeyword.c_str(), "POWER_Clamp_Reference" ) )
1483 else if( compareIbisWord( aKeyword.c_str(), "GND_Clamp_Reference" ) )
1485 else if( compareIbisWord( aKeyword.c_str(), "Rac" ) )
1487 else if( compareIbisWord( aKeyword.c_str(), "Cac" ) )
1489 else if( compareIbisWord( aKeyword.c_str(), "Rpower" ) )
1491 else if( compareIbisWord( aKeyword.c_str(), "Rgnd" ) )
1493 else
1494 {
1495 status = changeContext( aKeyword );
1496 }
1497 return status;
1498}
1499
1501{
1502 m_continue = IBIS_PARSER_CONTINUE::PACKAGEMODEL_PINS;
1503 std::string str;
1504
1505 if( readWord( str ) )
1506 m_currentPackageModel->m_pins.push_back( str );
1507
1508 return true;
1509}
1510
1511
1512bool IbisParser::readMatrixBanded( std::string aKeyword, IBIS_MATRIX_BANDED& aDest )
1513{
1514 bool status = true;
1515 m_continue = IBIS_PARSER_CONTINUE::MATRIX;
1516
1517 if( compareIbisWord( aKeyword.c_str(), "Bandwidth" ) )
1518 {
1519 if( m_currentMatrix->m_type == IBIS_MATRIX_TYPE::BANDED )
1520 {
1521 status &= readInt( aDest.m_bandwidth );
1522 if( status )
1523 {
1524 aDest.m_data.resize( aDest.m_bandwidth * aDest.m_dim );
1525 }
1526 }
1527 else
1528 {
1529 status = false;
1530 Report( _( "Cannot specify a bandwidth for that kind of matrix" ), RPT_SEVERITY_ERROR );
1531 }
1532 }
1533 if( !compareIbisWord( aKeyword.c_str(), "Dummy" ) )
1534 {
1535 int i;
1536 for( i = 0; i < aDest.m_bandwidth; i++ )
1537 {
1538 if( i + m_currentMatrixRowIndex >= aDest.m_bandwidth )
1539 {
1540 Report( "Too much data for this matrix row", RPT_SEVERITY_ERROR );
1541 status = false;
1542 break;
1543 }
1544
1545 int index = i + m_currentMatrixRow * aDest.m_bandwidth;
1546
1547 if( !readDouble( aDest.m_data[index] ) )
1548 {
1549 Report( _( "Invalid row in matrix" ), RPT_SEVERITY_ERROR );
1550 status = false;
1551 break;
1552 }
1553 }
1555 }
1556
1557 return status;
1558}
1559
1560
1561bool IbisParser::readMatrixFull( std::string aKeyword, IBIS_MATRIX_FULL& aDest )
1562{
1563 bool status = true;
1564 m_continue = IBIS_PARSER_CONTINUE::MATRIX;
1565
1566 if( !compareIbisWord( aKeyword.c_str(), "Dummy" ) )
1567 {
1568 std::vector<std::string> values;
1569
1570 status &= readTableLine( values );
1571 int i;
1572 for( i = 0; i < (int)values.size(); i++ )
1573 {
1574 int index = i + m_currentMatrixRow * aDest.m_dim + m_currentMatrixRow;
1575 // + final m_currentMatrixRow because we don't fill the lower triangle.
1576
1577 if( i >= ( aDest.m_dim - m_currentMatrixRow - m_currentMatrixRowIndex ) )
1578 {
1579 Report( _( "Too much data for this matrix row." ), RPT_SEVERITY_ERROR );
1580 status = false;
1581 break;
1582 }
1583
1584 if( index >= aDest.m_dim * aDest.m_dim )
1585 {
1586 status = false;
1587 Report( _( "Too much data for this matrix." ), RPT_SEVERITY_ERROR );
1588 break;
1589 }
1590 if( !parseDouble( aDest.m_data[index], values.at( i ), true ) )
1591 {
1592 Report( _( "Can't read a matrix element" ), RPT_SEVERITY_ERROR );
1593 status = false;
1594 }
1595 else
1596 {
1597 }
1598 }
1600 }
1601 return status;
1602}
1603
1604
1605bool IbisParser::readMatrixSparse( std::string aKeyword, IBIS_MATRIX_SPARSE& aDest )
1606{
1607 bool status = true;
1608
1609 if( !compareIbisWord( aKeyword.c_str(), "Dummy" ) )
1610 {
1611 int subindex;
1612 double value;
1613
1614 if( readInt( subindex ) )
1615 {
1616 if( readDouble( value ) )
1617 {
1618 #if 0
1619 // Currently not used
1620 int index = subindex + m_currentMatrixRow * aDest.m_dim + m_currentMatrixRow;
1621 #endif
1622 }
1623 else
1624 {
1625 Report( _( "Can't read a matrix element" ), RPT_SEVERITY_ERROR );
1626 }
1627 }
1628 else
1629 {
1630 Report( _( "Can't read a matrix index" ), RPT_SEVERITY_ERROR );
1631 }
1632 }
1633 return status;
1634}
1635
1636bool IbisParser::readMatrix( std::shared_ptr<IBIS_MATRIX> aDest )
1637{
1638 bool status = true;
1639 std::string str;
1640
1641 bool init = false;
1642
1643 if( aDest != nullptr )
1644 {
1645 if( aDest->m_type != IBIS_MATRIX_TYPE::BANDED && aDest->m_type != IBIS_MATRIX_TYPE::FULL
1646 && aDest->m_type != IBIS_MATRIX_TYPE::SPARSE )
1647 {
1648 init = false;
1649 }
1650 else
1651 {
1652 init = true;
1653 }
1654 }
1655 else
1656 {
1657 Report( "Matrix pointer is null." );
1658 status = false;
1659 }
1660
1661 if( m_continue != IBIS_PARSER_CONTINUE::MATRIX && status )
1662 {
1663 if( !init )
1664 {
1665 if( readWord( str ) )
1666 {
1667 IBIS_MATRIX* matrix;
1668
1669 if( compareIbisWord( str.c_str(), "Banded_matrix" ) )
1670 {
1671 matrix = static_cast<IBIS_MATRIX*>( new IBIS_MATRIX_BANDED( m_reporter ) );
1672 aDest = static_cast<std::shared_ptr<IBIS_MATRIX>>( matrix );
1673 m_currentMatrix = aDest;
1674 m_currentMatrix->m_type = IBIS_MATRIX_TYPE::BANDED;
1675 m_continue = IBIS_PARSER_CONTINUE::MATRIX;
1676 }
1677 else if( compareIbisWord( str.c_str(), "Full_matrix" ) )
1678 {
1679 matrix = static_cast<IBIS_MATRIX*>( new IBIS_MATRIX_FULL( m_reporter ) );
1680 aDest = static_cast<std::shared_ptr<IBIS_MATRIX>>( matrix );
1681 m_currentMatrix = aDest;
1683 m_currentMatrix->m_type = IBIS_MATRIX_TYPE::FULL;
1684 m_continue = IBIS_PARSER_CONTINUE::MATRIX;
1685 }
1686 else if( compareIbisWord( str.c_str(), "Sparse_matrix" ) )
1687 {
1688 matrix = static_cast<IBIS_MATRIX*>( new IBIS_MATRIX_SPARSE( m_reporter ) );
1689 aDest = static_cast<std::shared_ptr<IBIS_MATRIX>>( matrix );
1690 m_currentMatrix = aDest;
1691 m_currentMatrix->m_data.resize( matrix->m_dim * matrix->m_dim );
1692 m_currentMatrix->m_type = IBIS_MATRIX_TYPE::SPARSE;
1693 m_continue = IBIS_PARSER_CONTINUE::MATRIX;
1694 }
1695 else
1696 {
1697 status = false;
1698 Report( _( "Unknown matrix type" ), RPT_SEVERITY_ERROR );
1699 Report( str, RPT_SEVERITY_INFO );
1701 }
1702 }
1703 else
1704 {
1705 status = false;
1706 Report( _( "Missing matrix type" ), RPT_SEVERITY_ERROR );
1707 }
1708 }
1709 else
1710 {
1711 status = false;
1712 Report( _( " Matrix is already init. But m_continue was not set ( internal error )" ) );
1713 }
1714 }
1715 else
1716 {
1717 if( aDest != nullptr )
1718 {
1719 // If m_continue is set, ( and no keyword ) then it is a row
1720 switch( aDest->m_type )
1721 {
1722 case IBIS_MATRIX_TYPE::BANDED:
1723 readMatrixBanded( std::string( "Dummy" ),
1724 *static_cast<IBIS_MATRIX_BANDED*>( aDest.get() ) );
1725 break;
1726 case IBIS_MATRIX_TYPE::FULL:
1727 readMatrixFull( std::string( "Dummy" ),
1728 *static_cast<IBIS_MATRIX_FULL*>( aDest.get() ) );
1729 break;
1730 case IBIS_MATRIX_TYPE::SPARSE:
1731 readMatrixSparse( std::string( "Dummy" ),
1732 *static_cast<IBIS_MATRIX_SPARSE*>( aDest.get() ) );
1733 break;
1734 case IBIS_MATRIX_TYPE::UNDEFINED:
1735 default:
1736 {
1737 status = false;
1738 Report( _( "Tried to read a row from an undefined matrix" ) );
1739 }
1740 }
1741 }
1742 else
1743 {
1744 Report( _( "matrix pointer is null" ) );
1745 }
1746 }
1747 return status;
1748}
1749
1750bool IbisParser::parsePackageModelModelData( std::string& aKeyword )
1751{
1752 bool status = true;
1753
1754 if( compareIbisWord( aKeyword.c_str(), "Resistance_Matrix" ) )
1755 {
1756 IBIS_MATRIX dest( m_reporter ), source( m_reporter );
1758 }
1759 else if( compareIbisWord( aKeyword.c_str(), "Capacitance_Matrix" ) )
1760 {
1762 }
1763 else if( compareIbisWord( aKeyword.c_str(), "Inductance_Matrix" ) )
1764 {
1766 }
1767 else if( compareIbisWord( aKeyword.c_str(), "Bandwidth" ) )
1768 {
1769 status &= readMatrixBanded( aKeyword,
1770 *static_cast<IBIS_MATRIX_BANDED*>( m_currentMatrix.get() ) );
1771 }
1772 else if( compareIbisWord( aKeyword.c_str(), "Row" ) )
1773 {
1774 status &= readInt( m_currentMatrixRow );
1775 m_currentMatrixRow--; // The matrix starts at 0
1776 m_currentMatrixRowIndex = 0; // The matrix starts at 0*/
1777 m_continue = IBIS_PARSER_CONTINUE::MATRIX;
1778 }
1779 else if( compareIbisWord( aKeyword.c_str(), "End_Model_Data" ) )
1780 {
1781 m_context = IBIS_PARSER_CONTEXT::PACKAGEMODEL;
1782 m_continue = IBIS_PARSER_CONTINUE::NONE;
1783 }
1784 else
1785 {
1786 if( !changeContext( aKeyword ) )
1787 {
1788 status = false;
1789 }
1790 }
1791 return status;
1792}
1793
1794bool IbisParser::parsePackageModel( std::string& aKeyword )
1795{
1796 bool status = true;
1797
1798 if( compareIbisWord( aKeyword.c_str(), "Manufacturer" ) )
1800 else if( compareIbisWord( aKeyword.c_str(), "OEM" ) )
1801 status &= storeString( m_currentPackageModel->m_OEM, false );
1802 else if( compareIbisWord( aKeyword.c_str(), "Description" ) )
1803 status &= storeString( m_currentPackageModel->m_description, false );
1804 else if( compareIbisWord( aKeyword.c_str(), "Number_of_Pins" ) )
1806 else if( compareIbisWord( aKeyword.c_str(), "Pin_Numbers" ) )
1807 status &= readPackageModelPins();
1808 else if( compareIbisWord( aKeyword.c_str(), "Model_Data" ) )
1809 {
1810 m_context = IBIS_PARSER_CONTEXT::PACKAGEMODEL_MODELDATA;
1811 m_continue = IBIS_PARSER_CONTINUE::NONE;
1812 }
1813 else
1814 {
1815 if( !changeContext( aKeyword ) )
1816 {
1817 status = false;
1818 }
1819 }
1820 return status;
1821}
1822
1824{
1825 bool status = true;
1826
1828
1829 if( !readWord( model.m_modelName ) )
1830 return false;
1831
1832 status &= readString( model.m_modelDescription );
1833 m_currentModelSelector->m_models.push_back( model );
1834
1835 return status;
1836}
1837
1838bool IbisParser::readNumericSubparam( const std::string& aSubparam, double& aDest )
1839{
1840 std::string paramName;
1841 bool status = true;
1842
1843 if( aSubparam.size() >= (size_t)m_lineLength )
1844 {
1845 // Continuing would result in an overflow
1846 return false;
1847 }
1848
1849 int old_index = m_lineIndex;
1850 m_lineIndex = 0;
1851
1852
1853 for( size_t i = 0; i < aSubparam.size(); i++ )
1854 {
1855 paramName += m_buffer[m_lineOffset + m_lineIndex++];
1856 }
1857
1858 if( strcmp( paramName.c_str(), aSubparam.c_str() ) )
1859 {
1860 m_lineIndex = old_index;
1861 return false;
1862 }
1863
1865
1866 status &= m_buffer[m_lineOffset + m_lineIndex++] == '=';
1867
1868 if( status )
1869 {
1871 status &= readDouble( aDest );
1872 }
1873
1874 if( !status )
1875 {
1876 m_lineIndex = old_index;
1877 }
1878
1879 return status;
1880}
1881
1882
1884{
1885 bool status = true;
1886
1888
1889 std::string strValue;
1890
1891 if( !readDouble( aDest.value[IBIS_CORNER::TYP] ) )
1892 {
1893 Report( _( "Typ-Min-Max Values requires at least Typ." ), RPT_SEVERITY_ERROR );
1894 return false;
1895 }
1896
1897 readDouble( aDest.value[IBIS_CORNER::MIN] );
1898 readDouble( aDest.value[IBIS_CORNER::MAX] );
1899
1900 return status;
1901}
1902
1903bool IbisParser::readTypMinMaxValueSubparam( const std::string& aSubparam, TypMinMaxValue& aDest )
1904{
1905 std::string paramName;
1906 bool status = true;
1907
1908 m_lineIndex = 0; // rewind
1909
1910 if( aSubparam.size() < (size_t)m_lineLength )
1911 {
1912 for( size_t i = 0; i < aSubparam.size(); i++ )
1913 {
1914 paramName += m_buffer[m_lineOffset + m_lineIndex++];
1915 }
1916
1917 if( !strcmp( paramName.c_str(), aSubparam.c_str() ) )
1918 {
1919 readTypMinMaxValue( aDest );
1920 }
1921 else
1922 {
1923 status = false;
1924 }
1925 }
1926 else
1927 {
1928 status = false;
1929 }
1930
1931 return status;
1932}
1933
1935{
1936 bool status = true;
1937
1938 std::string subparam;
1939 if( readWord( subparam ) )
1940 {
1941 switch( m_continue )
1942 {
1943 case IBIS_PARSER_CONTINUE::MODEL:
1944
1945 if( !strcmp( subparam.substr( 0, 10 ).c_str(), "Model_type" ) )
1946 {
1947 if( readWord( subparam ) )
1948 {
1949 if( compareIbisWord( subparam.c_str(), "Input" ) )
1950 m_currentModel->m_type = IBIS_MODEL_TYPE::INPUT_STD;
1951 else if( compareIbisWord( subparam.c_str(), "Output" ) )
1952 m_currentModel->m_type = IBIS_MODEL_TYPE::OUTPUT;
1953 else if( compareIbisWord( subparam.c_str(), "I/O" ) )
1954 m_currentModel->m_type = IBIS_MODEL_TYPE::IO;
1955 else if( compareIbisWord( subparam.c_str(), "3-state" ) )
1956 m_currentModel->m_type = IBIS_MODEL_TYPE::THREE_STATE;
1957 else if( compareIbisWord( subparam.c_str(), "Open_drain" ) )
1958 m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_DRAIN;
1959 else if( compareIbisWord( subparam.c_str(), "I/O_Open_drain" ) )
1960 m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_DRAIN;
1961 else if( compareIbisWord( subparam.c_str(), "Open_sink" ) )
1962 m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_SINK;
1963 else if( compareIbisWord( subparam.c_str(), "I/O_open_sink" ) )
1964 m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_SINK;
1965 else if( compareIbisWord( subparam.c_str(), "Open_source" ) )
1966 m_currentModel->m_type = IBIS_MODEL_TYPE::OPEN_SOURCE;
1967 else if( compareIbisWord( subparam.c_str(), "I/O_open_source" ) )
1968 m_currentModel->m_type = IBIS_MODEL_TYPE::IO_OPEN_SOURCE;
1969 else if( compareIbisWord( subparam.c_str(), "Input_ECL" ) )
1970 m_currentModel->m_type = IBIS_MODEL_TYPE::INPUT_ECL;
1971 else if( compareIbisWord( subparam.c_str(), "Output_ECL" ) )
1972 m_currentModel->m_type = IBIS_MODEL_TYPE::OUTPUT_ECL;
1973 else if( compareIbisWord( subparam.c_str(), "I/O_ECL" ) )
1974 m_currentModel->m_type = IBIS_MODEL_TYPE::IO_ECL;
1975 else if( compareIbisWord( subparam.c_str(), "3-state_ECL" ) )
1976 m_currentModel->m_type = IBIS_MODEL_TYPE::THREE_STATE_ECL;
1977 else if( compareIbisWord( subparam.c_str(), "Terminator" ) )
1978 m_currentModel->m_type = IBIS_MODEL_TYPE::TERMINATOR;
1979 else if( compareIbisWord( subparam.c_str(), "Series" ) )
1980 m_currentModel->m_type = IBIS_MODEL_TYPE::SERIES;
1981 else if( compareIbisWord( subparam.c_str(), "Series_switch" ) )
1982 m_currentModel->m_type = IBIS_MODEL_TYPE::SERIES_SWITCH;
1983 else
1984 {
1985 std::stringstream message;
1986 message << _( "Unknown Model_type " ) << subparam;
1987 Report( message.str(), RPT_SEVERITY_ERROR );
1988 status = false;
1989 }
1990 }
1991 else
1992 {
1993 Report( _( "Internal Error while reading model_type" ), RPT_SEVERITY_ERROR );
1994 status = false;
1995 }
1996 }
1997 else if( !strcmp( subparam.substr( 0, 7 ).c_str(), "Enable" ) )
1998 {
1999 if( readWord( subparam ) )
2000 {
2001 if( !strcmp( subparam.c_str(), "Active-High" ) )
2002 m_currentModel->m_enable = IBIS_MODEL_ENABLE::ACTIVE_HIGH;
2003 else if( !strcmp( subparam.c_str(), "Active-Low" ) )
2004 m_currentModel->m_enable = IBIS_MODEL_ENABLE::ACTIVE_LOW;
2005 else
2006 {
2007 std::stringstream message;
2008 message << _( "Unknown Enable: " ) << subparam;
2009 Report( message.str(), RPT_SEVERITY_ERROR );
2010 status = false;
2011 }
2012 }
2013 else
2014 {
2015 Report( _( "Internal Error while reading Enable" ), RPT_SEVERITY_ERROR );
2016 status = false;
2017 }
2018 }
2019 else if( subparam.substr( 0, 9 ) == "Polarity" )
2020 {
2021 if( readWord( subparam ) )
2022 {
2023 if( subparam == "Inverting" )
2024 m_currentModel->m_polarity = IBIS_MODEL_POLARITY::INVERTING;
2025 else if( subparam == "Non-Inverting" )
2026 m_currentModel->m_polarity = IBIS_MODEL_POLARITY::NON_INVERTING;
2027 else
2028 {
2029 std::stringstream message;
2030 message << _( "Unknown polarity " ) << subparam;
2031 Report( message.str(), RPT_SEVERITY_ERROR );
2032 status = false;
2033 }
2034 }
2035 else
2036 {
2037 Report( _( "Internal Error while reading Enable" ), RPT_SEVERITY_ERROR );
2038 status = false;
2039 }
2040 }
2041 else if( readNumericSubparam( std::string( "Vinl" ), m_currentModel->m_vinl ) )
2042 ;
2043 else if( readNumericSubparam( std::string( "Vinh" ), m_currentModel->m_vinh ) )
2044 ;
2045 else if( readNumericSubparam( std::string( "Vref" ), m_currentModel->m_vref ) )
2046 ;
2047 else if( readNumericSubparam( std::string( "Rref" ), m_currentModel->m_rref ) )
2048 ;
2049 else if( readNumericSubparam( std::string( "Cref" ), m_currentModel->m_cref ) )
2050 ;
2051 else if( readNumericSubparam( std::string( "Vmeas" ), m_currentModel->m_vmeas ) )
2052 ;
2053 else if( readTypMinMaxValueSubparam( std::string( "C_comp" ),
2055 ;
2056 else
2057 {
2058 status = false;
2059 }
2060
2061 m_continue = IBIS_PARSER_CONTINUE::MODEL;
2062
2063 break;
2064
2065 default:
2066 status = false;
2067 Report( _( "Continued reading a model that did not begin. ( internal error )" ),
2069 }
2070 }
2071
2072 return status;
2073}
2074
2075
2076bool IbisParser::parseHeader( std::string& aKeyword )
2077{
2078 bool status = true;
2079
2080 if( compareIbisWord( aKeyword.c_str(), "IBIS_Ver" ) )
2081 {
2083 }
2084 else if( compareIbisWord( aKeyword.c_str(), "Comment_char" ) )
2085 {
2086 status &= changeCommentChar();
2087 }
2088 else if( compareIbisWord( aKeyword.c_str(), "File_Name" ) )
2089 {
2090 status &= storeString( m_ibisFile.m_header.m_fileName, false );
2091 }
2092 else if( compareIbisWord( aKeyword.c_str(), "File_Rev" ) )
2093 {
2095 }
2096 else if( compareIbisWord( aKeyword.c_str(), "Source" ) )
2097 {
2098 status &= storeString( m_ibisFile.m_header.m_source, true );
2099 }
2100 else if( compareIbisWord( aKeyword.c_str(), "Notes" ) )
2101 {
2102 status &= storeString( m_ibisFile.m_header.m_notes, true );
2103 }
2104 else if( compareIbisWord( aKeyword.c_str(), "Disclaimer" ) )
2105 {
2106 status &= storeString( m_ibisFile.m_header.m_disclaimer, true );
2107 }
2108 else if( compareIbisWord( aKeyword.c_str(), "Copyright" ) )
2109 {
2110 status &= storeString( m_ibisFile.m_header.m_copyright, true );
2111 }
2112 else if( compareIbisWord( aKeyword.c_str(), "Date" ) )
2113 {
2114 status &= storeString( m_ibisFile.m_header.m_date, false );
2115 }
2116 else
2117 {
2118 if( !changeContext( aKeyword ) )
2119 {
2120 status = false;
2121 }
2122 }
2123 return status;
2124}
2125
2126
2127bool IbisParser::parseComponent( std::string& aKeyword )
2128{
2129 bool status = true;
2130 if( compareIbisWord( aKeyword.c_str(), "Manufacturer" ) )
2131 {
2132 status &= storeString( m_currentComponent->m_manufacturer, true );
2133 }
2134 else if( compareIbisWord( aKeyword.c_str(), "Package" ) )
2135 {
2136 status &= readPackage();
2137 }
2138 else if( compareIbisWord( aKeyword.c_str(), "Pin" ) )
2139 {
2140 status &= readPin();
2141 }
2142 else if( compareIbisWord( aKeyword.c_str(), "Pin_Mapping" ) )
2143 {
2144 status &= readPinMapping();
2145 }
2146 else if( compareIbisWord( aKeyword.c_str(), "Diff_Pin" ) )
2147 {
2148 status &= readDiffPin();
2149 }
2150 /*
2151 // Not supported yet
2152 else if( aKeyword == "Die_Supply_Pads" )
2153 {
2154 status &= ReadDieSupplyPads();
2155 }*/
2156 else if( compareIbisWord( aKeyword.c_str(), "Package_Model" ) )
2157 {
2158 status &= storeString( m_currentComponent->m_packageModel, true );
2159 }
2160 else
2161 {
2162 if( !changeContext( aKeyword ) )
2163 {
2164 status = false;
2165 }
2166 }
2167 return status;
2168}
2169
2170bool IbisParser::readTableLine( std::vector<std::string>& aDest )
2171{
2172 aDest.clear();
2173
2174 while( m_lineIndex < m_lineLength )
2175 {
2176 std::string str;
2177
2178 while( ( !isspace( m_buffer[m_lineOffset + m_lineIndex] ) )
2179 && ( m_lineIndex < m_lineLength ) )
2180 {
2181 str += m_buffer[m_lineOffset + m_lineIndex++];
2182 }
2183
2184 if( str.size() > 0 )
2185 {
2186 aDest.push_back( str );
2187 }
2188 while( isspace( m_buffer[m_lineOffset + m_lineIndex] ) && ( m_lineIndex < m_lineLength ) )
2189 {
2190 m_lineIndex++;
2191 }
2192 }
2193 return true;
2194}
2195
2197{
2198 bool status = true;
2199
2200 std::vector<std::string> fields;
2201
2205
2206 readTableLine( fields );
2207
2208 int extraArg = ( m_continue == IBIS_PARSER_CONTINUE::NONE ) ? 1 : 0;
2209
2210 if( (int)fields.size() == ( 4 + extraArg ) )
2211 {
2212 TypMinMaxValue* cValue;
2213
2214 if( fields.at( 0 ) == "R_pkg" )
2215 cValue = R;
2216 else if( fields.at( 0 ) == "L_pkg" )
2217 cValue = L;
2218 else if( fields.at( 0 ) == "C_pkg" )
2219 cValue = C;
2220 else
2221 {
2222 Report( "Invalid field in [Package]" );
2223 return false;
2224 }
2225 status &= parseDouble( cValue->value[IBIS_CORNER::TYP], fields.at( 1 ), true );
2226 // Min / max values are optional, so don't update the status
2227 parseDouble( cValue->value[IBIS_CORNER::MIN], fields.at( 2 ), true );
2228 parseDouble( cValue->value[IBIS_CORNER::MAX], fields.at( 3 ), true );
2229 }
2230 else
2231 {
2232 if( fields.size() != 0 )
2233 {
2234 Report( _( "A [Package] line requires exactly 4 elements." ), RPT_SEVERITY_ERROR );
2235 status = false;
2236 }
2237 }
2238 m_continue = IBIS_PARSER_CONTINUE::COMPONENT_PACKAGE;
2239
2240 return status;
2241}
2242
2243
2245{
2246 bool status = true;
2247
2248 std::vector<std::string> fields;
2249
2250 m_lineIndex = 0;
2251 status &= readTableLine( fields );
2252
2254
2255 if( ( fields.size() == 3 ) )
2256 {
2257 if( m_continue == IBIS_PARSER_CONTINUE::COMPONENT_PIN ) // No info on first line
2258 {
2259 pin.m_pinName = fields.at( 0 );
2260 pin.m_signalName = fields.at( 1 );
2261 pin.m_modelName = fields.at( 2 );
2262 pin.m_Rcol = m_currentComponent->m_pins.back().m_Rcol;
2263 pin.m_Lcol = m_currentComponent->m_pins.back().m_Lcol;
2264 pin.m_Ccol = m_currentComponent->m_pins.back().m_Ccol;
2265
2266 m_currentComponent->m_pins.push_back( pin );
2267 }
2268 else
2269 {
2270 pin.m_dummy = true;
2271 }
2272 }
2273 else
2274 {
2275 if( m_continue == IBIS_PARSER_CONTINUE::COMPONENT_PIN ) // Not on the first line
2276 {
2277 pin.m_pinName = fields.at( 0 );
2278 pin.m_signalName = fields.at( 1 );
2279 pin.m_modelName = fields.at( 2 );
2280
2281 pin.m_Rcol = m_currentComponent->m_pins.back().m_Rcol;
2282 pin.m_Lcol = m_currentComponent->m_pins.back().m_Lcol;
2283 pin.m_Ccol = m_currentComponent->m_pins.back().m_Ccol;
2284
2285 if( pin.m_Rcol == 0 || pin.m_Lcol == 0 || pin.m_Ccol == 0 )
2286 {
2287 Report( _( "Invalid pin entry: 6 values from a table with only 3." ),
2289 status = false; // Did we just try to go from a 3 column table to a 6 ?
2290 }
2291 else
2292 {
2293 if( !parseDouble( pin.m_Rpin, fields.at( pin.m_Rcol ), true )
2294 || !parseDouble( pin.m_Lpin, fields.at( pin.m_Lcol ), true )
2295 || !parseDouble( pin.m_Cpin, fields.at( pin.m_Ccol ), true ) )
2296 {
2297 Report( _( "Can't read a R, L or C value for a pin." ), RPT_SEVERITY_ERROR );
2298 status = false;
2299 }
2300 }
2301 }
2302 else
2303 {
2304 for( int i = 3; i < 6; i++ )
2305 {
2306 if( fields.at( i ) == "R_pin" )
2307 {
2308 pin.m_Rcol = i;
2309 }
2310 else if( fields.at( i ) == "L_pin" )
2311 {
2312 pin.m_Lcol = i;
2313 }
2314 else if( fields.at( i ) == "C_pin" )
2315 {
2316 pin.m_Ccol = i;
2317 }
2318 else
2319 {
2320 Report( _( "Invalid field name in [Pin]" ), RPT_SEVERITY_ERROR );
2321 status = false;
2322 }
2323 }
2324
2325 if( pin.m_Rcol == 0 || pin.m_Lcol == 0 || pin.m_Ccol == 0 )
2326 {
2327 Report( _( "Missing argument in [Pin]" ), RPT_SEVERITY_ERROR );
2328 status = false;
2329 }
2330 pin.m_dummy = true;
2331 }
2332 }
2333
2334 m_currentComponent->m_pins.push_back( pin );
2335 m_continue = IBIS_PARSER_CONTINUE::COMPONENT_PIN;
2336
2337
2338 return status;
2339}
2340
2341
2343{
2344 bool status = true;
2345
2346 std::vector<std::string> fields;
2347
2348 status &= readTableLine( fields );
2349
2350 IbisComponentPinMapping pinMapping( m_reporter );
2351
2352 if( m_continue == IBIS_PARSER_CONTINUE::NONE ) // No info on first line
2353 {
2354 m_continue = IBIS_PARSER_CONTINUE::COMPONENT_PINMAPPING;
2355 }
2356 else
2357 {
2358 if( fields.size() != 0 )
2359 {
2360 if( fields.size() > 6 || fields.size() < 3 )
2361 {
2362 Report( _( "Wrong number of columns for pin mapping." ), RPT_SEVERITY_ERROR );
2363 status = false;
2364 }
2365 else
2366 {
2367 pinMapping.m_pinName = fields.at( 0 );
2368 pinMapping.m_PDref = fields.at( 1 );
2369 pinMapping.m_PUref = fields.at( 2 );
2370
2371 if( fields.size() > 3 )
2372 pinMapping.m_GNDClampRef = fields.at( 3 );
2373
2374 if( fields.size() > 4 )
2375 pinMapping.m_POWERClampRef = fields.at( 4 );
2376
2377 if( fields.size() > 5 )
2378 pinMapping.m_extRef = fields.at( 5 );
2379 }
2380 m_currentComponent->m_pinMappings.push_back( pinMapping );
2381 }
2382 }
2383 return status;
2384}
2385
2386
2388{
2389 bool status = true;
2390
2391 m_lineIndex = 0; // rewind
2393
2394 if( m_continue == IBIS_PARSER_CONTINUE::NONE ) // No info on first line
2395 {
2396 m_continue = IBIS_PARSER_CONTINUE::COMPONENT_DIFFPIN;
2397 }
2398 else
2399 {
2400 if( !readWord( entry.pinA ) )
2401 {
2402 Report( _( "Incorrect diff pin name" ), RPT_SEVERITY_ERROR );
2403 status = false;
2404 }
2405 if( !readWord( entry.pinB ) )
2406 {
2407 Report( _( "Incorrect inv_pin name" ), RPT_SEVERITY_ERROR );
2408 status = false;
2409 }
2410 if( status )
2411 {
2412 m_currentComponent->m_diffPin.m_entries.push_back( entry );
2413 }
2414 }
2415 return status;
2416}
2417
2418
2420{
2421 bool status = true;
2422
2424
2425 IVtableEntry entry( m_reporter );
2426
2428 {
2429 std::string str;
2430
2431 status &= readDouble( entry.V );
2432
2433 if( status && readTypMinMaxValue( entry.I ) )
2434 {
2435 aDest.m_entries.push_back( entry );
2436 }
2437 }
2438
2439 m_continue = IBIS_PARSER_CONTINUE::IV_TABLE;
2440 m_currentIVtable = &aDest;
2441
2442
2443 return status;
2444}
2445
2447{
2448 bool status = true;
2450
2451 VTtableEntry entry( m_reporter );
2452
2454 {
2455 std::string str;
2456 status &= readDouble( entry.t );
2457 status &= readTypMinMaxValue( entry.V );
2458 }
2459
2460 m_continue = IBIS_PARSER_CONTINUE::IV_TABLE;
2461 m_currentVTtable = &aDest;
2462
2463 if( status )
2464 {
2465 aDest.m_entries.push_back( entry );
2466 }
2467
2468 return status;
2469}
2470
2472{
2473 bool status = true;
2474
2475
2476 IbisWaveform* wf;
2477
2478 if( m_continue != IBIS_PARSER_CONTINUE::WAVEFORM )
2479 {
2480 wf = new IbisWaveform( m_reporter );
2481 wf->m_type = aType;
2482
2483 switch( aType )
2484 {
2485 case IBIS_WAVEFORM_TYPE::FALLING: m_currentModel->m_fallingWaveforms.push_back( wf ); break;
2486 case IBIS_WAVEFORM_TYPE::RISING: m_currentModel->m_risingWaveforms.push_back( wf ); break;
2487 default: Report( _( "Unknown waveform type" ), RPT_SEVERITY_ERROR ); status = false;
2488 }
2489 }
2490 else
2491 {
2492 if( aDest != nullptr )
2493 {
2494 wf = aDest;
2495 }
2496 else
2497 {
2498 Report( _( "Internal error detected, a waveform should exist" ), RPT_SEVERITY_ERROR );
2499 return false;
2500 }
2501 }
2502
2503
2504 if( status & !isLineEmptyFromCursor() )
2505 {
2506 // readNumericSubparam() returns true if it could read the subparameter and store it
2507 // Testing all subparameters
2508 if( readNumericSubparam( std::string( "R_fixture" ), wf->m_R_fixture ) )
2509 ;
2510 else if( readNumericSubparam( std::string( "L_fixture" ), wf->m_L_fixture ) )
2511 ;
2512 else if( readNumericSubparam( std::string( "C_fixture" ), wf->m_C_fixture ) )
2513 ;
2514 else if( readNumericSubparam( std::string( "V_fixture" ), wf->m_V_fixture ) )
2515 ;
2516 else if( readNumericSubparam( std::string( "V_fixture_min" ), wf->m_V_fixture_min ) )
2517 ;
2518 else if( readNumericSubparam( std::string( "V_fixture_max" ), wf->m_V_fixture_max ) )
2519 ;
2520 else if( readNumericSubparam( std::string( "R_dut" ), wf->m_R_fixture ) )
2521 ;
2522 else if( readNumericSubparam( std::string( "L_dut" ), wf->m_L_fixture ) )
2523 ;
2524 else if( readNumericSubparam( std::string( "C_dut" ), wf->m_C_fixture ) )
2525 ;
2526 // The line is not a subparameter, then let's try to read a VT table entry
2528 {
2529 status = false;
2530 }
2531 }
2532 m_currentWaveform = wf;
2533 m_continue = IBIS_PARSER_CONTINUE::WAVEFORM;
2534 return status;
2535}
2536
2538{
2539 bool status = true;
2540 char c;
2541 std::string keyword = getKeyword();
2542
2543 if( keyword.size() > 0 ) // New keyword
2544 {
2545
2546 if( m_continue != IBIS_PARSER_CONTINUE::NONE )
2547 {
2548 m_continue = IBIS_PARSER_CONTINUE::NONE;
2549 }
2550 switch( m_context )
2551 {
2552 case IBIS_PARSER_CONTEXT::HEADER: status &= parseHeader( keyword ); break;
2553 case IBIS_PARSER_CONTEXT::COMPONENT: status &= parseComponent( keyword ); break;
2554 case IBIS_PARSER_CONTEXT::MODELSELECTOR: status &= parseModelSelector( keyword ); break;
2555 case IBIS_PARSER_CONTEXT::MODEL: status &= parseModel( keyword ); break;
2556 case IBIS_PARSER_CONTEXT::PACKAGEMODEL: status &= parsePackageModel( keyword ); break;
2557 case IBIS_PARSER_CONTEXT::PACKAGEMODEL_MODELDATA:
2558 status &= parsePackageModelModelData( keyword );
2559 break;
2560 default:
2561 {
2562 status = false;
2563 Report( _( "Internal error: Bad parser context." ), RPT_SEVERITY_ERROR );
2564 }
2565 }
2566 }
2567 else
2568 {
2570 if( m_lineIndex == m_lineLength )
2571 {
2572 // That was an empty line
2573 return true;
2574 }
2575
2576 // No new keyword ? Then it is the continuation of the previous one !
2577 switch( m_continue )
2578 {
2579 case IBIS_PARSER_CONTINUE::STRING:
2581 *m_continuingString += '\n';
2582 status &= readString( *m_continuingString );
2583 break;
2584 case IBIS_PARSER_CONTINUE::COMPONENT_PACKAGE: status &= readPackage(); break;
2585 case IBIS_PARSER_CONTINUE::COMPONENT_PIN: status &= readPin(); break;
2586 case IBIS_PARSER_CONTINUE::COMPONENT_PINMAPPING: status &= readPinMapping(); break;
2587 case IBIS_PARSER_CONTINUE::COMPONENT_DIFFPIN: status &= readDiffPin(); break;
2588 case IBIS_PARSER_CONTINUE::MODELSELECTOR: status &= readModelSelector(); break;
2589 case IBIS_PARSER_CONTINUE::MODEL: status &= readModel(); break;
2590 case IBIS_PARSER_CONTINUE::IV_TABLE: status &= readIVtableEntry( *m_currentIVtable ); break;
2591 case IBIS_PARSER_CONTINUE::VT_TABLE: status &= readVTtableEntry( *m_currentVTtable ); break;
2592 case IBIS_PARSER_CONTINUE::WAVEFORM:
2594 break;
2595 case IBIS_PARSER_CONTINUE::RAMP: status &= readRamp(); break;
2596 case IBIS_PARSER_CONTINUE::MODEL_SPEC: status &= readModelSpec(); break;
2597 case IBIS_PARSER_CONTINUE::PACKAGEMODEL_PINS: status &= readPackageModelPins(); break;
2598 case IBIS_PARSER_CONTINUE::MATRIX: status &= readMatrix( m_currentMatrix ); break;
2599 case IBIS_PARSER_CONTINUE::NONE:
2600 default:
2601 Report( _( "Missing keyword." ), RPT_SEVERITY_ERROR );
2602 return false;
2603 break;
2604 }
2605 }
2607
2608 while( ( c != '\n' ) && ( c != 0 ) ) // Go to the end of line
2609 {
2611 }
2612 return status;
2613}
REPORTER * m_reporter
Definition: ibis_parser.h:56
void Report(std::string aMsg, SEVERITY aSeverity=RPT_SEVERITY_INFO) const
Print a message.
Definition: ibis_parser.h:65
static std::string doubleToString(double aNumber)
Convert a double to string using scientific notation.
std::vector< double > m_data
Definition: ibis_parser.h:128
bool Check() override
Check if the data held by the object is valid.
Definition: ibis_parser.cpp:61
bool Check() override
Check if the data held by the object is valid.
Definition: ibis_parser.cpp:90
std::vector< double > m_data
Definition: ibis_parser.h:151
bool Check() override
Check if the data held by the object is valid.
std::vector< double > m_data
Definition: ibis_parser.h:139
TypMinMaxValue I
Definition: ibis_parser.h:348
bool Check() override
Check if the data held by the object is valid.
double InterpolatedI(double aV, IBIS_CORNER aCorner) const
Interpolate the IV table.
std::vector< IVtableEntry > m_entries
Definition: ibis_parser.h:359
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.
bool Check() override
Check if the data held by the object is valid.
TypMinMaxValue m_Cpkg
Definition: ibis_parser.h:203
TypMinMaxValue m_Lpkg
Definition: ibis_parser.h:202
TypMinMaxValue m_Rpkg
Definition: ibis_parser.h:201
std::string m_GNDClampRef
Definition: ibis_parser.h:249
std::string m_POWERClampRef
Definition: ibis_parser.h:250
bool Check() override
Check if the data held by the object is valid.
std::string m_signalName
Definition: ibis_parser.h:220
std::string m_pinName
Definition: ibis_parser.h:219
std::string m_modelName
Definition: ibis_parser.h:221
std::string m_manufacturer
Definition: ibis_parser.h:298
std::string m_packageModel
Definition: ibis_parser.h:302
std::vector< IbisComponentPinMapping > m_pinMappings
Definition: ibis_parser.h:301
IbisComponentPackage m_package
Definition: ibis_parser.h:299
bool Check() override
Check if the data held by the object is valid.
IbisDiffPin m_diffPin
Definition: ibis_parser.h:305
std::string m_name
Definition: ibis_parser.h:297
std::vector< IbisComponentPin > m_pins
Definition: ibis_parser.h:300
std::string pinB
Definition: ibis_parser.h:269
std::string pinA
Definition: ibis_parser.h:268
std::vector< IbisDiffPinEntry > m_entries
Definition: ibis_parser.h:282
std::vector< IbisComponent > m_components
Definition: ibis_parser.h:615
IbisHeader m_header
Definition: ibis_parser.h:614
std::vector< IbisPackageModel > m_packageModels
Definition: ibis_parser.h:618
std::vector< IbisModel > m_models
Definition: ibis_parser.h:617
std::vector< IbisModelSelector > m_modelSelectors
Definition: ibis_parser.h:616
bool Check() override
Check if the data held by the object is valid.
std::string m_fileName
Definition: ibis_parser.h:170
std::string m_copyright
Definition: ibis_parser.h:175
std::string m_notes
Definition: ibis_parser.h:173
double m_ibisVersion
Definition: ibis_parser.h:168
std::string m_date
Definition: ibis_parser.h:172
std::string m_source
Definition: ibis_parser.h:171
double m_fileRevision
Definition: ibis_parser.h:169
std::string m_disclaimer
Definition: ibis_parser.h:174
std::string m_modelName
Definition: ibis_parser.h:314
std::string m_modelDescription
Definition: ibis_parser.h:315
bool Check() override
Check if the data held by the object is valid.
std::vector< IbisModelSelectorEntry > m_models
Definition: ibis_parser.h:330
IBIS_MODEL_TYPE m_type
Definition: ibis_parser.h:543
double m_cref
Definition: ibis_parser.h:550
IVtable m_pullup
Definition: ibis_parser.h:569
TypMinMaxValue m_Cac
Definition: ibis_parser.h:566
TypMinMaxValue m_pullupReference
Definition: ibis_parser.h:559
double m_vmeas
Definition: ibis_parser.h:551
IVtable m_pulldown
Definition: ibis_parser.h:570
bool Check() override
Check if the data held by the object is valid.
TypMinMaxValue m_Rac
Definition: ibis_parser.h:565
std::vector< IbisWaveform * > m_risingWaveforms
Definition: ibis_parser.h:571
IVtable m_POWERClamp
Definition: ibis_parser.h:568
TypMinMaxValue m_Rgnd
Definition: ibis_parser.h:563
TypMinMaxValue m_POWERClampReference
Definition: ibis_parser.h:562
IVtable m_GNDClamp
Definition: ibis_parser.h:567
IbisRamp m_ramp
Definition: ibis_parser.h:573
IBIS_MODEL_POLARITY m_polarity
Definition: ibis_parser.h:553
TypMinMaxValue m_C_comp
Definition: ibis_parser.h:556
double m_rref
Definition: ibis_parser.h:549
IBIS_MODEL_ENABLE m_enable
Definition: ibis_parser.h:552
TypMinMaxValue m_temperatureRange
Definition: ibis_parser.h:558
std::vector< IbisWaveform * > m_fallingWaveforms
Definition: ibis_parser.h:572
TypMinMaxValue m_pulldownReference
Definition: ibis_parser.h:560
double m_vref
Definition: ibis_parser.h:548
TypMinMaxValue m_GNDClampReference
Definition: ibis_parser.h:561
double m_vinh
Definition: ibis_parser.h:547
double m_vinl
Definition: ibis_parser.h:546
TypMinMaxValue m_voltageRange
Definition: ibis_parser.h:557
TypMinMaxValue m_Rpower
Definition: ibis_parser.h:564
std::string m_name
Definition: ibis_parser.h:542
std::vector< std::string > m_pins
Definition: ibis_parser.h:594
std::shared_ptr< IBIS_MATRIX > m_resistanceMatrix
Definition: ibis_parser.h:596
std::string m_OEM
Definition: ibis_parser.h:591
std::shared_ptr< IBIS_MATRIX > m_inductanceMatrix
Definition: ibis_parser.h:598
bool Check() override
Check if the data held by the object is valid.
std::string m_description
Definition: ibis_parser.h:592
std::string m_name
Definition: ibis_parser.h:589
std::shared_ptr< IBIS_MATRIX > m_capacitanceMatrix
Definition: ibis_parser.h:597
std::string m_manufacturer
Definition: ibis_parser.h:590
std::vector< char > m_buffer
Definition: ibis_parser.h:662
char m_commentChar
Definition: ibis_parser.h:661
long m_lineCounter
Definition: ibis_parser.h:660
IBIS_PARSER_CONTINUE m_continue
Definition: ibis_parser.h:800
bool readPin()
bool readModelSpec()
bool changeCommentChar()
Ibis can change the character used for comments.
bool getNextLine()
Load the next line.
bool parseComponent(std::string &aKeyword)
Parse a single keyword in the component context.
bool parseModel(std::string &aKeyword)
Parse a single keyword in the model selector context.
bool readMatrixFull(std::string, IBIS_MATRIX_FULL &aDest)
VTtable * m_currentVTtable
Definition: ibis_parser.h:677
bool isLineEmptyFromCursor()
void printLine()
Print the current line.
bool readModelSelector()
bool changeContext(std::string &aKeyword)
int m_currentMatrixRowIndex
Definition: ibis_parser.h:675
std::string getKeyword()
bool parseDouble(double &aDest, std::string &aStr, bool aAllowModifiers=false)
Parse a double according to the ibis standard.
bool onNewLine()
Parse the current line.
bool readWord(std::string &aDest)
bool readTypMinMaxValue(TypMinMaxValue &aDest)
bool compareIbisWord(const std::string &a, const std::string &b)
compare two strings without being case sensitive
Definition: ibis_parser.cpp:51
int m_currentMatrixRow
Definition: ibis_parser.h:674
IbisComponent * m_currentComponent
Definition: ibis_parser.h:669
std::shared_ptr< IBIS_MATRIX > m_currentMatrix
Definition: ibis_parser.h:673
int m_lineLength
Definition: ibis_parser.h:666
int m_lineIndex
Definition: ibis_parser.h:665
bool readDvdt(std::string &aString, dvdt &aDest)
bool ParseFile(const std::string &aFileName)
Parse a file.
std::string * m_continuingString
Definition: ibis_parser.h:690
IbisModel * m_currentModel
Definition: ibis_parser.h:671
bool m_parrot
Definition: ibis_parser.h:658
bool readModel()
int m_lineOffset
Definition: ibis_parser.h:664
bool parsePackageModelModelData(std::string &)
Parse a single keyword in the package model context.
IbisPackageModel * m_currentPackageModel
Definition: ibis_parser.h:672
bool readDouble(double &aDest)
IbisModelSelector * m_currentModelSelector
Definition: ibis_parser.h:670
bool readRamp()
bool checkEndofLine()
bool parsePackageModel(std::string &aKeyword)
Parse a single keyword in the model context.
bool readString(std::string &aDest)
bool readPinMapping()
bool readTypMinMaxValueSubparam(const std::string &aSubparam, TypMinMaxValue &aDest)
bool readMatrixBanded(std::string, IBIS_MATRIX_BANDED &aDest)
bool readNumericSubparam(const std::string &aSubparam, double &aDest)
bool readMatrix(std::shared_ptr< IBIS_MATRIX > aDest)
bool readInt(int &aDest)
bool readPackage()
int m_bufferIndex
Definition: ibis_parser.h:663
IBIS_PARSER_CONTEXT m_context
Definition: ibis_parser.h:801
IbisFile m_ibisFile
Definition: ibis_parser.h:668
IVtable * m_currentIVtable
Definition: ibis_parser.h:676
bool readIVtableEntry(IVtable &aTable)
bool readVTtableEntry(VTtable &aTable)
bool parseModelSelector(std::string &aKeyword)
Parse a single keyword in the component context.
bool readDiffPin()
void skipWhitespaces()
bool storeString(std::string &aDest, bool aMultiline)
bool readPackageModelPins()
bool readRampdvdt(dvdtTypMinMax &aDest)
bool readTableLine(std::vector< std::string > &aDest)
bool readMatrixSparse(std::string, IBIS_MATRIX_SPARSE &aDest)
bool parseHeader(std::string &aKeyword)
Parse a single keyword in the header context.
bool readWaveform(IbisWaveform *aDest, IBIS_WAVEFORM_TYPE aType)
IbisWaveform * m_currentWaveform
Definition: ibis_parser.h:678
dvdtTypMinMax m_rising
Definition: ibis_parser.h:479
bool Check() override
Check if the data held by the object is valid.
double m_Rload
Definition: ibis_parser.h:480
dvdtTypMinMax m_falling
Definition: ibis_parser.h:478
double m_L_fixture
Definition: ibis_parser.h:503
double m_V_fixture
Definition: ibis_parser.h:504
VTtable m_table
Definition: ibis_parser.h:496
double m_V_fixture_min
Definition: ibis_parser.h:505
IBIS_WAVEFORM_TYPE m_type
Definition: ibis_parser.h:497
double m_V_fixture_max
Definition: ibis_parser.h:506
double m_R_fixture
Definition: ibis_parser.h:501
double m_C_fixture
Definition: ibis_parser.h:502
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:49
bool Check() override
Check if the data held by the object is valid.
double value[3]
Definition: ibis_parser.h:185
TypMinMaxValue V
Definition: ibis_parser.h:403
std::vector< VTtableEntry > m_entries
Definition: ibis_parser.h:413
dvdt value[3]
Definition: ibis_parser.h:463
bool Check() override
Check if the data held by the object is valid.
double m_dv
Definition: ibis_parser.h:455
double m_dt
Definition: ibis_parser.h:456
#define _(s)
bool isNumberNA(double aNumber)
#define NAN_NA
Definition: ibis_parser.h:35
IBIS_CORNER
Definition: ibis_parser.h:94
#define IBIS_MAX_VERSION
Definition: ibis_parser.h:38
#define NAN_INVALID
Definition: ibis_parser.h:36
#define IBIS_MAX_LINE_LENGTH
Definition: ibis_parser.h:39
IBIS_WAVEFORM_TYPE
Definition: ibis_parser.h:486
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
static std::string strValue(double aValue)