KiCad PCB EDA Suite
Loading...
Searching...
No Matches
netlist_exporter_allegro.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <confirm.h>
25#include <refdes_utils.h>
26#include <sch_edit_frame.h>
27#include <sch_reference_list.h>
28#include <string_utils.h>
29#include <connection_graph.h>
30#include <core/kicad_algo.h>
31#include <symbol_library.h>
32#include <symbol_lib_table.h>
33#include <netlist.h>
36#include <regex>
37
38
39bool NETLIST_EXPORTER_ALLEGRO::WriteNetlist( const wxString& aOutFileName,
40 unsigned /* aNetlistOptions */,
41 REPORTER& aReporter )
42{
43 m_f = nullptr;
44 int ret = 0; // zero now, OR in the sign bit on error
45
46 // Create the devices directory
47 m_exportPath = wxFileName( aOutFileName ).GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR )
48 + wxString( "devices" );
49 if( !wxDirExists( m_exportPath ) )
50 {
51 if( !wxMkdir( m_exportPath, wxS_DIR_DEFAULT ) )
52 {
53 wxString msg = wxString::Format( _( "Failed to create directory 'devices' ." ) );
54 aReporter.Report( msg, RPT_SEVERITY_ERROR );
55 return false;
56 }
57 }
58
59 // Write the netlist file
60 if( ( m_f = wxFopen( aOutFileName, wxT( "wt" ) ) ) == nullptr )
61 {
62 wxString msg = wxString::Format( _( "Failed to create file '%s'." ), aOutFileName );
63 aReporter.Report( msg, RPT_SEVERITY_ERROR );
64 return false;
65 }
66
67 ret |= fprintf( m_f, "(Source: %s)\n", TO_UTF8( m_schematic->GetFileName() ) );
68 ret |= fprintf( m_f, "(Date: %s)\n", TO_UTF8( GetISO8601CurrentDateTime() ) );
69
70 m_packageProperties.clear();
71 m_componentGroups.clear();
73 m_netNameNodes.clear();
74
76
77 // Start with package definitions, which we create from component groups.
79
80 // Write out nets
82
83 // Write out package properties. NOTE: Allegro doesn't recognize much...
85
86 // Done with the netlist
87 fclose( m_f );
88
89 m_f = nullptr;
90
91 return ret >= 0;
92}
93
94
96 SCH_SHEET_PATH>& aItem1,
97 const std::pair<SCH_SYMBOL*,
98 SCH_SHEET_PATH>& aItem2 )
99{
100 wxString refText1 = aItem1.first->GetRef( &aItem1.second );
101 wxString refText2 = aItem2.first->GetRef( &aItem2.second );
102
103 if( refText1 == refText2 )
104 {
105 return aItem1.second.PathHumanReadable() < aItem2.second.PathHumanReadable();
106 }
107
108 return CompareSymbolRef( refText1, refText2 );
109}
110
111
112bool NETLIST_EXPORTER_ALLEGRO::CompareSymbolRef( const wxString& aRefText1,
113 const wxString& aRefText2 )
114{
115 if( removeTailDigits( aRefText1 ) == removeTailDigits( aRefText2 ) )
116 {
117 return extractTailNumber( aRefText1 ) < extractTailNumber( aRefText2 );
118 }
119
120 return aRefText1 < aRefText2;
121}
122
123
125{
126 // return "lhs < rhs"
127 return StrNumCmp( aPin1->GetShownNumber(), aPin2->GetShownNumber(), true ) < 0;
128}
129
130
132{
134 m_libParts.clear();
135
136 for( const SCH_SHEET_PATH& sheet : m_schematic->Hierarchy() )
137 {
139
140 auto cmp =
141 [&sheet]( SCH_SYMBOL* a, SCH_SYMBOL* b )
142 {
143 return ( StrNumCmp( a->GetRef( &sheet, false ),
144 b->GetRef( &sheet, false ), true ) < 0 );
145 };
146
147 std::set<SCH_SYMBOL*, decltype( cmp )> ordered_symbols( cmp );
148 std::multiset<SCH_SYMBOL*, decltype( cmp )> extra_units( cmp );
149
150 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
151 {
152 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
153 auto test = ordered_symbols.insert( symbol );
154
155 if( !test.second )
156 {
157 if( ( *( test.first ) )->m_Uuid > symbol->m_Uuid )
158 {
159 extra_units.insert( *( test.first ) );
160 ordered_symbols.erase( test.first );
161 ordered_symbols.insert( symbol );
162 }
163 else
164 {
165 extra_units.insert( symbol );
166 }
167 }
168 }
169
170 for( EDA_ITEM* item : ordered_symbols )
171 {
172 SCH_SYMBOL* symbol = findNextSymbol( item, sheet );
173
174 if( !symbol || symbol->GetExcludedFromBoard() )
175 continue;
176
177 if( symbol->GetLibPins().empty() )
178 continue;
179
180 m_packageProperties.insert( std::pair<wxString,
181 wxString>( sheet.PathHumanReadable(),
182 symbol->GetRef( &sheet ) ) );
183 m_orderedSymbolsSheetpath.push_back( std::pair<SCH_SYMBOL*,
184 SCH_SHEET_PATH>( symbol, sheet ) );
185 }
186 }
187
188 struct NET_RECORD
189 {
190 NET_RECORD( const wxString& aName ) :
191 m_Name( aName )
192 {};
193
194 wxString m_Name;
195 std::vector<NET_NODE> m_Nodes;
196 };
197
198 std::vector<NET_RECORD*> nets;
199
200 for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
201 {
202 wxString net_name = it.first.Name;
203 const std::vector<CONNECTION_SUBGRAPH*>& subgraphs = it.second;
204 NET_RECORD* net_record = nullptr;
205
206 if( subgraphs.empty() )
207 continue;
208
209 nets.emplace_back( new NET_RECORD( net_name ) );
210 net_record = nets.back();
211
212 for( CONNECTION_SUBGRAPH* subgraph : subgraphs )
213 {
214 bool nc = subgraph->GetNoConnect() &&
215 subgraph->GetNoConnect()->Type() == SCH_NO_CONNECT_T;
216 const SCH_SHEET_PATH& sheet = subgraph->GetSheet();
217
218 for( SCH_ITEM* item : subgraph->GetItems() )
219 {
220 if( item->Type() == SCH_PIN_T )
221 {
222 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
223 SYMBOL* symbol = pin->GetParentSymbol();
224
225 if( !symbol || symbol->GetExcludedFromBoard() )
226 continue;
227
228 net_record->m_Nodes.emplace_back( pin, sheet, nc );
229 }
230 }
231 }
232 }
233
234 // Netlist ordering: Net name, then ref des, then pin name
235 std::sort( nets.begin(), nets.end(),
236 []( const NET_RECORD* a, const NET_RECORD*b )
237 {
238 return StrNumCmp( a->m_Name, b->m_Name ) < 0;
239 } );
240
241 for( NET_RECORD* net_record : nets )
242 {
243 // Netlist ordering: Net name, then ref des, then pin name
244 std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
245 []( const NET_NODE& a, const NET_NODE& b )
246 {
247 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
248 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
249
250 if( refA == refB )
251 return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
252
253 return refA < refB;
254 } );
255
256 // Some duplicates can exist, for example on multi-unit parts with duplicated pins across
257 // units. If the user connects the pins on each unit, they will appear on separate
258 // subgraphs. Remove those here:
259 alg::remove_duplicates( net_record->m_Nodes,
260 []( const NET_NODE& a, const NET_NODE& b )
261 {
262 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
263 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
264
265 return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
266 } );
267
268 for( const NET_NODE& netNode : net_record->m_Nodes )
269 {
270 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
271
272 // Skip power symbols and virtual symbols
273 if( refText[0] == wxChar( '#' ) )
274 {
275 continue;
276 }
277
278 m_netNameNodes.insert( std::pair<wxString, NET_NODE>( net_record->m_Name, netNode ) );
279 }
280 }
281
282 for( NET_RECORD* record : nets )
283 delete record;
284}
285
286
288{
289 int groupCount = 1;
290 wxString deviceFileCreatingError = wxString( "" );
291
292 //Group the components......
293 while(!m_orderedSymbolsSheetpath.empty())
294 {
295 std::pair<SCH_SYMBOL*, SCH_SHEET_PATH> first_ele = m_orderedSymbolsSheetpath.front();
296 m_orderedSymbolsSheetpath.pop_front();
297 m_componentGroups.insert( std::pair<int, std::pair<SCH_SYMBOL*,
298 SCH_SHEET_PATH>>( groupCount, first_ele ) );
299
300 for( auto it = m_orderedSymbolsSheetpath.begin(); it != m_orderedSymbolsSheetpath.end();
301 ++it )
302 {
303 if( it->first->GetValue( false, &it->second, false )
304 != first_ele.first->GetValue( false, &first_ele.second, false ) )
305 {
306 continue;
307 }
308
309 if( it->first->GetFootprintFieldText( false, &it->second, false )
310 != first_ele.first->GetFootprintFieldText( false, &first_ele.second, false ) )
311 {
312 continue;
313 }
314
315 wxString ref1 = it->first->GetRef( &it->second );
316 wxString ref2 = first_ele.first->GetRef( &first_ele.second );
317
318 if( removeTailDigits( ref1 ) == removeTailDigits( ref2 ) )
319 {
320 m_componentGroups.insert( std::pair<int, std::pair<SCH_SYMBOL*,
321 SCH_SHEET_PATH>>( groupCount, ( *it ) ) );
322 it = m_orderedSymbolsSheetpath.erase( it );
323
324 if( std::distance( it, m_orderedSymbolsSheetpath.begin() ) > 0 )
325 it--;
326 else if( it == m_orderedSymbolsSheetpath.end() )
327 break;
328 }
329 }
330 groupCount++;
331 }
332
333 struct COMP_PACKAGE_STRUCT
334 {
335 wxString m_value;
336 wxString m_tolerance;
337 std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> m_symbolSheetpaths;
338 };
339
340 COMP_PACKAGE_STRUCT compPackageStruct;
341 std::map<wxString, COMP_PACKAGE_STRUCT> compPackageMap;
342
343 for( int groupIndex = 1; groupIndex < groupCount; groupIndex++ )
344 {
345 auto pairIter = m_componentGroups.equal_range( groupIndex );
346 auto beginIter = pairIter.first;
347 auto endIter = pairIter.second;
348
349 SCH_SYMBOL* sym = ( beginIter->second ).first;
350 SCH_SHEET_PATH sheetPath = ( beginIter->second ).second;
351
352 wxString valueText = sym->GetValue( false, &sheetPath, false );
353 wxString footprintText = sym->GetFootprintFieldText( false, &sheetPath, false);
354 wxString deviceType = valueText + wxString("_") + footprintText;
355
356 while( deviceType.GetChar(deviceType.Length()-1) == '_' )
357 {
358 deviceType.RemoveLast();
359 }
360
361 deviceType = formatDevice( deviceType );
362
363 wxArrayString fieldArray;
364 fieldArray.Add( "Spice_Model" );
365 fieldArray.Add( "VALUE" );
366
367 wxString value = getGroupField( groupIndex, fieldArray );
368
369 fieldArray.clear();
370 fieldArray.Add( "TOLERANCE" );
371 fieldArray.Add( "TOL" );
372 wxString tol = getGroupField( groupIndex, fieldArray );
373
374 std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths;
375
376 for( auto iter = beginIter; iter != endIter; iter++ )
377 {
378 symbolSheetpaths.push_back( std::pair<SCH_SYMBOL*,
379 SCH_SHEET_PATH>( iter->second.first,
380 iter->second.second ) );
381 }
382
383 std::stable_sort( symbolSheetpaths.begin(), symbolSheetpaths.end(),
385
386 compPackageStruct.m_value = value;
387 compPackageStruct.m_tolerance = tol;
388 compPackageStruct.m_symbolSheetpaths = symbolSheetpaths;
389 compPackageMap.insert( std::pair( deviceType, compPackageStruct ) );
390
391 // Write out the corresponding device file
392 FILE* d = nullptr;
393 wxString deviceFileName = wxFileName( m_exportPath, deviceType,
394 wxString( "txt" ) ).GetFullPath();
395
396 if( ( d = wxFopen( deviceFileName, wxT( "wt" ) ) ) == nullptr )
397 {
398 wxString msg;
399 msg.Printf( _( "Failed to create file '%s'.\n" ), deviceFileName );
400 deviceFileCreatingError += msg;
401 continue;
402 }
403
404 footprintText = footprintText.AfterLast( ':' );
405
406 wxArrayString footprintAlt;
407 wxArrayString footprintArray = sym->GetLibSymbolRef()->GetFPFilters();
408
409 for( const wxString& fp : footprintArray )
410 {
411 if( ( fp.Find( '*' ) != wxNOT_FOUND ) || ( fp.Find( '?' ) != wxNOT_FOUND ) )
412 {
413 continue;
414 }
415
416 footprintAlt.Add( fp.AfterLast( ':' ) );
417 }
418
419 if( footprintText.IsEmpty() )
420 {
421 if( !footprintAlt.IsEmpty() )
422 {
423 footprintText = footprintAlt[0];
424 footprintAlt.RemoveAt( 0 );
425 }
426 else
427 {
428 footprintText = deviceType;
429 }
430 }
431
432 fprintf( d, "PACKAGE '%s'\n", TO_UTF8( formatDevice( footprintText ) ) );
433 fprintf( d, "CLASS IC\n" );
434
435 std::vector<SCH_PIN*> pinList = sym->GetLibSymbolRef()->GetPins();
436
437 /*
438 * We must erase redundant Pins references in pinList
439 * These redundant pins exist because some pins are found more than one time when a
440 * symbol has multiple parts per package or has 2 representations (DeMorgan conversion).
441 * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes, and
442 * therefore each pin appears 2 times in the list. Common pins (VCC, GND) can also be
443 * found more than once.
444 */
445 sort( pinList.begin(), pinList.end(), NETLIST_EXPORTER_ALLEGRO::CompareLibPin );
446
447 for( int ii = 0; ii < (int) pinList.size() - 1; ii++ )
448 {
449 if( pinList[ii]->GetNumber() == pinList[ii + 1]->GetNumber() )
450 {
451 // 2 pins have the same number, remove the redundant pin at index i+1
452 pinList.erase( pinList.begin() + ii + 1 );
453 ii--;
454 }
455 }
456
457 unsigned int pinCount = pinList.size();
458 fprintf( d, "PINCOUNT %u\n", pinCount );
459
460 if( pinCount > 0 )
461 {
462 fprintf( d, "%s", TO_UTF8( formatFunction( "main", pinList ) ) );
463 }
464
465 if( !value.IsEmpty() )
466 {
467 fprintf( d, "PACKAGEPROP VALUE %s\n", TO_UTF8( value ) );
468 }
469
470 if( !tol.IsEmpty() )
471 {
472 fprintf( d, "PACKAGEPROP TOL %s\n", TO_UTF8( tol ) );
473 }
474
475 if( !footprintAlt.IsEmpty() )
476 {
477 fprintf( d, "PACKAGEPROP ALT_SYMBOLS '(" );
478
479 wxString footprintAltSymbolsText;
480
481 for( const wxString& fp : footprintAlt )
482 {
483 footprintAltSymbolsText += fp + wxString( "," );
484 }
485
486 footprintAltSymbolsText.Truncate( footprintAltSymbolsText.Length() - 1 );
487 fprintf( d, "%s)'\n", TO_UTF8( footprintAltSymbolsText ) );
488 }
489
490 wxArrayString propArray;
491 propArray.Add( "PART_NUMBER" );
492 propArray.Add( "mpn" );
493 propArray.Add( "mfr_pn" );
494 wxString data = getGroupField( groupIndex, propArray );
495
496 if(!data.IsEmpty())
497 {
498 fprintf( d, "PACKAGEPROP %s %s\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
499 }
500
501 propArray.clear();
502 propArray.Add( "HEIGHT" );
503 data = getGroupField( groupIndex, propArray );
504
505 if(!data.IsEmpty())
506 {
507 fprintf( d, "PACKAGEPROP %s %s\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
508 }
509
510 fprintf( d, "END\n" );
511
512 fclose( d );
513 }
514
515 for( auto iter = compPackageMap.begin(); iter != compPackageMap.end(); iter++ )
516 {
517 wxString deviceType = iter->first;
518 wxString value = iter->second.m_value;
519 wxString tolerance = iter->second.m_tolerance;
520
521 if( value.IsEmpty() && tolerance.IsEmpty() )
522 {
523 fprintf( m_f, "!%s;", TO_UTF8( deviceType ) );
524 }
525 else if( tolerance.IsEmpty() )
526 {
527 fprintf( m_f, "!%s!%s;", TO_UTF8( deviceType ), TO_UTF8( value ) );
528 }
529 else
530 {
531 fprintf( m_f, "!%s!%s!%s;", TO_UTF8( deviceType ), TO_UTF8( value ),
532 TO_UTF8( tolerance ) );
533 }
534
535 std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths =
536 iter->second.m_symbolSheetpaths;
537
538 for( const auto& [ sym, sheetPath ] : symbolSheetpaths)
539 fprintf( m_f, ",\n\t%s", TO_UTF8( sym->GetRef( &sheetPath ) ) );
540
541 fprintf( m_f, "\n" );
542 }
543
544 if( !deviceFileCreatingError.IsEmpty() )
545 DisplayError( nullptr, deviceFileCreatingError );
546}
547
548
549wxString NETLIST_EXPORTER_ALLEGRO::formatText( wxString aString )
550{
551 if( aString.IsEmpty() )
552 return wxEmptyString;
553
554 aString.Replace( "\u03BC", "u" );
555
556 std::regex reg( "[!']|[^ -~]" );
557 wxString processedString = wxString( std::regex_replace( std::string( aString ), reg, "?" ) );
558
559 std::regex search_reg( "[^a-zA-Z0-9_/]" );
560
561 if( std::regex_search( std::string( processedString ), search_reg ) )
562 return wxString( "'" ) + processedString + wxString( "'" );
563
564 return processedString;
565}
566
567
569{
570 wxString pinName4Telesis = aPin.GetName() + wxString( "__" ) + aPin.GetNumber();
571 std::regex reg( "[^A-Za-z0-9_+?/-]" );
572 return wxString( std::regex_replace( std::string( pinName4Telesis ), reg, "?" ) );
573}
574
575
576wxString NETLIST_EXPORTER_ALLEGRO::formatFunction( wxString aName, std::vector<SCH_PIN*> aPinList )
577{
578 aName.MakeUpper();
579 std::list<wxString> pinNameList;
580
581 std::stable_sort( aPinList.begin(), aPinList.end(), NETLIST_EXPORTER_ALLEGRO::CompareLibPin );
582
583 for( auto pin : aPinList )
584 pinNameList.push_back( formatPin( *pin ) );
585
586 wxString out_str = "";
587 wxString str;
588
589 out_str.Printf( wxT( "PINORDER %s " ), TO_UTF8( aName ) );
590
591 for( const wxString& pinName : pinNameList )
592 {
593 str.Printf( ",\n\t%s", TO_UTF8( pinName ) );
594 out_str += str;
595 }
596 out_str += wxString( "\n" );
597
598 str.Printf( wxT( "FUNCTION %s %s " ), TO_UTF8( aName ), TO_UTF8( aName ) );
599 out_str += str;
600
601 for( auto pin : aPinList )
602 {
603 str.Printf( ",\n\t%s", TO_UTF8( pin->GetNumber() ) );
604 out_str += str;
605 }
606
607 out_str += wxString( "\n" );
608
609 return out_str;
610}
611
612
613wxString NETLIST_EXPORTER_ALLEGRO::getGroupField( int aGroupIndex, const wxArrayString& aFieldArray,
614 bool aSanitize )
615{
616 auto pairIter = m_componentGroups.equal_range( aGroupIndex );
617
618 for( auto iter = pairIter.first; iter != pairIter.second; ++iter )
619 {
620 SCH_SYMBOL* sym = ( iter->second ).first;
621 SCH_SHEET_PATH sheetPath = ( iter->second ).second;
622
623 for( const wxString& field : aFieldArray )
624 {
625 if( SCH_FIELD* fld = sym->FindFieldCaseInsensitive( field ) )
626 {
627 wxString fieldText = fld->GetShownText( &sheetPath, true );
628
629 if( !fieldText.IsEmpty() )
630 {
631 if( aSanitize )
632 return formatText( fieldText );
633 else
634 return fieldText;
635 }
636 }
637 }
638 }
639
640 for( auto iter = pairIter.first; iter != pairIter.second; ++iter )
641 {
642 SCH_SYMBOL* sym = ( iter->second ).first;
643
644 for( const wxString& field : aFieldArray )
645 {
646 if( SCH_FIELD* fld = sym->GetLibSymbolRef()->FindFieldCaseInsensitive( field ) )
647 {
648 wxString fieldText = fld->GetShownText( false, 0 );
649
650 if( !fieldText.IsEmpty() )
651 {
652 if( aSanitize )
653 return formatText( fieldText );
654 else
655 return fieldText;
656 }
657 }
658 }
659 }
660
661 return wxEmptyString;
662}
663
664
665wxString NETLIST_EXPORTER_ALLEGRO::formatDevice( wxString aString )
666{
667 aString.MakeLower();
668 std::regex reg( "[^a-z0-9_-]" );
669 return wxString( std::regex_replace( std::string( aString ), reg, "_" ) );
670}
671
672
674{
675 fprintf( m_f, "%s\n", "$PACKAGES" );
676 fprintf( m_f, "%s\n", "$A_PROPERTIES" );
677
678 while( !m_packageProperties.empty() )
679 {
680 std::multimap<wxString, wxString>::iterator iter = m_packageProperties.begin();
681 wxString sheetPathText = iter->first;
682
683 fprintf( m_f, "ROOM %s;", TO_UTF8( formatText( sheetPathText ) ) );
684
685 std::vector<wxString> refTexts;
686
687 auto pairIter = m_packageProperties.equal_range( sheetPathText );
688
689 for( iter = pairIter.first; iter != pairIter.second; ++iter )
690 {
691 wxString refText = iter->second;
692 refTexts.push_back( refText );
693 }
694
695 m_packageProperties.erase( pairIter.first, pairIter.second );
696
697 std::stable_sort( refTexts.begin(), refTexts.end(),
699
700 for( const wxString& ref : refTexts )
701 fprintf( m_f, ",\n\t%s", TO_UTF8( ref ) );
702
703 fprintf( m_f, "\n" );
704 }
705}
706
707
709{
710 fprintf( m_f, "%s\n", "$NETS" );
711
712 while( !m_netNameNodes.empty() )
713 {
714 std::multimap<wxString, NET_NODE>::iterator iter = m_netNameNodes.begin();
715 std::vector<NET_NODE> netNodes;
716
717 wxString netName = iter->first;
718
719 fprintf( m_f, "%s;", TO_UTF8( formatText( netName ).MakeUpper() ) );
720
721 auto pairIter = m_netNameNodes.equal_range( netName );
722
723 for( iter = pairIter.first; iter != pairIter.second; ++iter )
724 {
725 NET_NODE netNode = iter->second;
726 netNodes.push_back( netNode );
727 }
728
729 m_netNameNodes.erase( pairIter.first, pairIter.second );
730
731 std::stable_sort( netNodes.begin(), netNodes.end() );
732
733 for( const NET_NODE& netNode : netNodes )
734 {
735 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
736 wxString pinText = netNode.m_Pin->GetShownNumber();
737 fprintf( m_f, ",\n\t%s.%s", TO_UTF8( refText ), TO_UTF8( pinText ) );
738 }
739
740 fprintf( m_f, "\n" );
741 }
742}
743
744
746{
747 while( ( aString.GetChar( aString.Length() - 1 ) >= '0' )
748 && ( aString.GetChar( aString.Length() - 1 ) <= '9' ) )
749 {
750 aString.RemoveLast();
751 }
752
753 return aString;
754}
755
756
757unsigned int NETLIST_EXPORTER_ALLEGRO::extractTailNumber( wxString aString )
758{
759 wxString numString;
760
761 while( ( aString.GetChar( aString.Length() - 1 ) >= '0' )
762 && ( aString.GetChar( aString.Length() - 1 ) <= '9' ) )
763 {
764 numString.insert( 0, aString.GetChar( aString.Length() - 1 ) );
765 aString.RemoveLast();
766 }
767
768 unsigned long val;
769
770 //From wxWidgets 3.1.6, here we can use ToUInt instead of ToULong function.
771 numString.ToULong( &val );
772 return (unsigned int) val;
773}
const NET_MAP & GetNetMap() const
A subgraph is a set of items that are electrically connected on a single sheet.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:98
const KIID m_Uuid
Definition: eda_item.h:516
wxString formatDevice(wxString aString)
Convert a string into one safe for a Telesis device name.
wxString m_exportPath
Directory to store device files.
static unsigned int extractTailNumber(wxString aString)
Extract the str's tailing number.
FILE * m_f
File pointer for netlist file writing operation.
static wxString removeTailDigits(wxString aString)
Remove the str's tailing digits.
void toAllegroPackageProperties()
Write $A_PROPERTIES section.
bool WriteNetlist(const wxString &aOutFileName, unsigned aNetlistOptions, REPORTER &aReporter) override
Write netlist to aOutFileName.
std::list< std::pair< SCH_SYMBOL *, SCH_SHEET_PATH > > m_orderedSymbolsSheetpath
Store the ordered symbols with sheetpath.
static bool CompareSymbolSheetpath(const std::pair< SCH_SYMBOL *, SCH_SHEET_PATH > &aItem1, const std::pair< SCH_SYMBOL *, SCH_SHEET_PATH > &aItem2)
Compare two std::pair<SCH_SYMBOL*, SCH_SHEET_PATH> variables.
wxString formatText(wxString aString)
Convert a string into Telesis-safe format.
std::multimap< wxString, wxString > m_packageProperties
wxString formatFunction(wxString aName, std::vector< SCH_PIN * > aPinList)
Generate the definition of a function in Telesis format, which consists of multiple declarations (PIN...
static bool CompareLibPin(const SCH_PIN *aPin1, const SCH_PIN *aPin2)
Compare two SCH_PIN* variables.
wxString formatPin(const SCH_PIN &aPin)
Generate a Telesis-compatible pin name from a pin node.
static bool CompareSymbolRef(const wxString &aRefText1, const wxString &aRefText2)
Compare two wxString variables.
wxString getGroupField(int aGroupIndex, const wxArrayString &aFieldArray, bool aSanitize=true)
Look up a field for a component group, which may have mismatched case, or the component group may not...
void toAllegroPackages()
Write the $PACKAGES section.
std::multimap< wxString, NET_NODE > m_netNameNodes
Store the NET_NODE with the net name.
std::multimap< int, std::pair< SCH_SYMBOL *, SCH_SHEET_PATH > > m_componentGroups
Store the component group.
void toAllegroNets()
Write the $NETS section.
SCHEMATIC * m_schematic
The schematic we're generating a netlist for.
SCH_SYMBOL * findNextSymbol(EDA_ITEM *aItem, const SCH_SHEET_PATH &aSheetPath)
Check if the given symbol should be processed for netlisting.
std::set< LIB_SYMBOL *, LIB_SYMBOL_LESS_THAN > m_libParts
unique library symbols used. LIB_SYMBOL items are sorted by names
UNIQUE_STRINGS m_referencesAlreadyFound
Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than once.
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition: reporter.h:102
void SetCurrentSheet(const SCH_SHEET_PATH &aPath)
Definition: schematic.h:176
wxString GetFileName() const
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:350
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:258
CONNECTION_GRAPH * ConnectionGraph() const
Definition: schematic.h:183
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:168
const SYMBOL * GetParentSymbol() const
Definition: sch_item.cpp:252
wxString GetShownNumber() const
Definition: sch_pin.cpp:535
const wxString & GetName() const
Definition: sch_pin.cpp:357
const wxString & GetNumber() const
Definition: sch_pin.h:123
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
const SCH_SHEET * GetSheet(unsigned aIndex) const
Schematic symbol object.
Definition: sch_symbol.h:75
const wxString GetValue(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const override
Definition: sch_symbol.cpp:728
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
Search for a SCH_FIELD with aFieldName.
Definition: sch_symbol.cpp:838
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const
Definition: sch_symbol.cpp:744
std::vector< SCH_PIN * > GetLibPins() const
Populate a vector with all the pins from the library object that match the current unit and bodyStyle...
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
Definition: sch_symbol.h:183
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
Definition: sch_symbol.cpp:558
A base class for LIB_SYMBOL and SCH_SYMBOL.
Definition: symbol.h:63
virtual const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const =0
bool GetExcludedFromBoard() const override
Definition: symbol.h:187
void Clear()
Erase the record.
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:169
This file is part of the common library.
#define _(s)
void remove_duplicates(_Container &__c)
Deletes all duplicate values from __c.
Definition: kicad_algo.h:161
Collection of utility functions for component reference designators (refdes)
@ RPT_SEVERITY_ERROR
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
wxString GetISO8601CurrentDateTime()
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:429
Definition for symbol library class.
@ SCH_NO_CONNECT_T
Definition: typeinfo.h:161
@ SCH_SYMBOL_T
Definition: typeinfo.h:173
@ SCH_PIN_T
Definition: typeinfo.h:154