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