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#include <fmt.h>
38#include <fmt/ranges.h>
39
40bool NETLIST_EXPORTER_ALLEGRO::WriteNetlist( const wxString& aOutFileName,
41 unsigned /* aNetlistOptions */,
42 REPORTER& aReporter )
43{
44 m_f = nullptr;
45 bool success = true;
46
47 // Create the devices directory
48 m_exportPath = wxFileName( aOutFileName ).GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR )
49 + wxString( "devices" );
50 if( !wxDirExists( m_exportPath ) )
51 {
52 if( !wxMkdir( m_exportPath, wxS_DIR_DEFAULT ) )
53 {
54 wxString msg = wxString::Format( _( "Failed to create directory 'devices' ." ) );
55 aReporter.Report( msg, RPT_SEVERITY_ERROR );
56 return false;
57 }
58 }
59
60 // Write the netlist file
61 if( ( m_f = wxFopen( aOutFileName, wxT( "wt" ) ) ) == nullptr )
62 {
63 wxString msg = wxString::Format( _( "Failed to create file '%s'." ), aOutFileName );
64 aReporter.Report( msg, RPT_SEVERITY_ERROR );
65 return false;
66 }
67
68 try
69 {
70 fmt::print( m_f, "(NETLIST)\n" );
71 fmt::print( m_f, "(Source: {})\n", TO_UTF8( m_schematic->GetFileName() ) );
72 fmt::print( m_f, "(Date: {})\n", TO_UTF8( GetISO8601CurrentDateTime() ) );
73
74 m_packageProperties.clear();
75 m_componentGroups.clear();
77 m_netNameNodes.clear();
78
80
81 // Start with package definitions, which we create from component groups.
83
84 // Write out package properties. NOTE: Allegro doesn't recognize much...
86
87 // Write out nets
89
90 fmt::print( m_f, "$END\n" );
91 }
92 catch (...)
93 {
94 success = false;
95 }
96
97 // Done with the netlist
98 fclose( m_f );
99
100 m_f = nullptr;
101
102 return success;
103}
104
105
107 SCH_SHEET_PATH>& aItem1,
108 const std::pair<SCH_SYMBOL*,
109 SCH_SHEET_PATH>& aItem2 )
110{
111 wxString refText1 = aItem1.first->GetRef( &aItem1.second );
112 wxString refText2 = aItem2.first->GetRef( &aItem2.second );
113
114 if( refText1 == refText2 )
115 {
116 return aItem1.second.PathHumanReadable() < aItem2.second.PathHumanReadable();
117 }
118
119 return CompareSymbolRef( refText1, refText2 );
120}
121
122
123bool NETLIST_EXPORTER_ALLEGRO::CompareSymbolRef( const wxString& aRefText1,
124 const wxString& aRefText2 )
125{
126 if( removeTailDigits( aRefText1 ) == removeTailDigits( aRefText2 ) )
127 {
128 return extractTailNumber( aRefText1 ) < extractTailNumber( aRefText2 );
129 }
130
131 return aRefText1 < aRefText2;
132}
133
134
136{
137 // return "lhs < rhs"
138 return StrNumCmp( aPin1->GetShownNumber(), aPin2->GetShownNumber(), true ) < 0;
139}
140
141
143{
145 m_libParts.clear();
146
147 for( const SCH_SHEET_PATH& sheet : m_schematic->Hierarchy() )
148 {
149 m_schematic->SetCurrentSheet( sheet );
150
151 auto cmp =
152 [&sheet]( SCH_SYMBOL* a, SCH_SYMBOL* b )
153 {
154 return ( StrNumCmp( a->GetRef( &sheet, false ),
155 b->GetRef( &sheet, false ), true ) < 0 );
156 };
157
158 std::set<SCH_SYMBOL*, decltype( cmp )> ordered_symbols( cmp );
159 std::multiset<SCH_SYMBOL*, decltype( cmp )> extra_units( cmp );
160
161 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
162 {
163 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
164 auto test = ordered_symbols.insert( symbol );
165
166 if( !test.second )
167 {
168 if( ( *( test.first ) )->m_Uuid > symbol->m_Uuid )
169 {
170 extra_units.insert( *( test.first ) );
171 ordered_symbols.erase( test.first );
172 ordered_symbols.insert( symbol );
173 }
174 else
175 {
176 extra_units.insert( symbol );
177 }
178 }
179 }
180
181 for( EDA_ITEM* item : ordered_symbols )
182 {
183 SCH_SYMBOL* symbol = findNextSymbol( item, sheet );
184
185 if( !symbol || symbol->GetExcludedFromBoard() )
186 continue;
187
188 if( symbol->GetLibPins().empty() )
189 continue;
190
191 m_packageProperties.insert( std::pair<wxString,
192 wxString>( sheet.PathHumanReadable(),
193 symbol->GetRef( &sheet ) ) );
194 m_orderedSymbolsSheetpath.push_back( std::pair<SCH_SYMBOL*,
195 SCH_SHEET_PATH>( symbol, sheet ) );
196 }
197 }
198
199 struct NET_RECORD
200 {
201 NET_RECORD( const wxString& aName ) :
202 m_Name( aName )
203 {};
204
205 wxString m_Name;
206 std::vector<NET_NODE> m_Nodes;
207 };
208
209 std::vector<NET_RECORD*> nets;
210
211 for( const auto& it : m_schematic->ConnectionGraph()->GetNetMap() )
212 {
213 wxString net_name = it.first.Name;
214 const std::vector<CONNECTION_SUBGRAPH*>& subgraphs = it.second;
215 NET_RECORD* net_record = nullptr;
216
217 if( subgraphs.empty() )
218 continue;
219
220 nets.emplace_back( new NET_RECORD( net_name ) );
221 net_record = nets.back();
222
223 for( CONNECTION_SUBGRAPH* subgraph : subgraphs )
224 {
225 bool nc = subgraph->GetNoConnect() &&
226 subgraph->GetNoConnect()->Type() == SCH_NO_CONNECT_T;
227 const SCH_SHEET_PATH& sheet = subgraph->GetSheet();
228
229 for( SCH_ITEM* item : subgraph->GetItems() )
230 {
231 if( item->Type() == SCH_PIN_T )
232 {
233 SCH_PIN* pin = static_cast<SCH_PIN*>( item );
234 SYMBOL* symbol = pin->GetParentSymbol();
235
236 if( !symbol || symbol->GetExcludedFromBoard() )
237 continue;
238
239 net_record->m_Nodes.emplace_back( pin, sheet, nc );
240 }
241 }
242 }
243 }
244
245 // Netlist ordering: Net name, then ref des, then pin name
246 std::sort( nets.begin(), nets.end(),
247 []( const NET_RECORD* a, const NET_RECORD*b )
248 {
249 return StrNumCmp( a->m_Name, b->m_Name ) < 0;
250 } );
251
252 for( NET_RECORD* net_record : nets )
253 {
254 // Netlist ordering: Net name, then ref des, then pin name
255 std::sort( net_record->m_Nodes.begin(), net_record->m_Nodes.end(),
256 []( const NET_NODE& a, const NET_NODE& b )
257 {
258 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
259 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
260
261 if( refA == refB )
262 return a.m_Pin->GetShownNumber() < b.m_Pin->GetShownNumber();
263
264 return refA < refB;
265 } );
266
267 // Some duplicates can exist, for example on multi-unit parts with duplicated pins across
268 // units. If the user connects the pins on each unit, they will appear on separate
269 // subgraphs. Remove those here:
270 alg::remove_duplicates( net_record->m_Nodes,
271 []( const NET_NODE& a, const NET_NODE& b )
272 {
273 wxString refA = a.m_Pin->GetParentSymbol()->GetRef( &a.m_Sheet );
274 wxString refB = b.m_Pin->GetParentSymbol()->GetRef( &b.m_Sheet );
275
276 return refA == refB && a.m_Pin->GetShownNumber() == b.m_Pin->GetShownNumber();
277 } );
278
279 for( const NET_NODE& netNode : net_record->m_Nodes )
280 {
281 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
282
283 // Skip power symbols and virtual symbols
284 if( refText[0] == wxChar( '#' ) )
285 {
286 continue;
287 }
288
289 m_netNameNodes.insert( std::pair<wxString, NET_NODE>( net_record->m_Name, netNode ) );
290 }
291 }
292
293 for( NET_RECORD* record : nets )
294 delete record;
295}
296
297
299{
300 int groupCount = 1;
301 wxString deviceFileCreatingError = wxString( "" );
302
303 //Group the components......
304 while(!m_orderedSymbolsSheetpath.empty())
305 {
306 std::pair<SCH_SYMBOL*, SCH_SHEET_PATH> first_ele = m_orderedSymbolsSheetpath.front();
307 m_orderedSymbolsSheetpath.pop_front();
308 m_componentGroups.insert( std::pair<int, std::pair<SCH_SYMBOL*,
309 SCH_SHEET_PATH>>( groupCount, first_ele ) );
310
311 for( auto it = m_orderedSymbolsSheetpath.begin(); it != m_orderedSymbolsSheetpath.end();
312 ++it )
313 {
314 if( it->first->GetValue( false, &it->second, false )
315 != first_ele.first->GetValue( false, &first_ele.second, false ) )
316 {
317 continue;
318 }
319
320 if( it->first->GetFootprintFieldText( false, &it->second, false )
321 != first_ele.first->GetFootprintFieldText( false, &first_ele.second, false ) )
322 {
323 continue;
324 }
325
326 wxString ref1 = it->first->GetRef( &it->second );
327 wxString ref2 = first_ele.first->GetRef( &first_ele.second );
328
329 if( removeTailDigits( ref1 ) == removeTailDigits( ref2 ) )
330 {
331 m_componentGroups.insert( std::pair<int, std::pair<SCH_SYMBOL*,
332 SCH_SHEET_PATH>>( groupCount, ( *it ) ) );
333 it = m_orderedSymbolsSheetpath.erase( it );
334
335 if( std::distance( it, m_orderedSymbolsSheetpath.begin() ) > 0 )
336 it--;
337 else if( it == m_orderedSymbolsSheetpath.end() )
338 break;
339 }
340 }
341 groupCount++;
342 }
343
344 struct COMP_PACKAGE_STRUCT
345 {
346 wxString m_value;
347 wxString m_tolerance;
348 std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> m_symbolSheetpaths;
349 };
350
351 COMP_PACKAGE_STRUCT compPackageStruct;
352 std::map<wxString, COMP_PACKAGE_STRUCT> compPackageMap;
353
354 for( int groupIndex = 1; groupIndex < groupCount; groupIndex++ )
355 {
356 auto pairIter = m_componentGroups.equal_range( groupIndex );
357 auto beginIter = pairIter.first;
358 auto endIter = pairIter.second;
359
360 SCH_SYMBOL* sym = ( beginIter->second ).first;
361 SCH_SHEET_PATH sheetPath = ( beginIter->second ).second;
362
363 wxString valueText = sym->GetValue( false, &sheetPath, false );
364 wxString footprintText = sym->GetFootprintFieldText( false, &sheetPath, false);
365 wxString deviceType = valueText + wxString("_") + footprintText;
366
367 while( deviceType.GetChar(deviceType.Length()-1) == '_' )
368 {
369 deviceType.RemoveLast();
370 }
371
372 deviceType = formatDevice( deviceType );
373
374 wxArrayString fieldArray;
375 fieldArray.Add( "Spice_Model" );
376 fieldArray.Add( "VALUE" );
377
378 wxString value = getGroupField( groupIndex, fieldArray );
379
380 fieldArray.clear();
381 fieldArray.Add( "TOLERANCE" );
382 fieldArray.Add( "TOL" );
383 wxString tol = getGroupField( groupIndex, fieldArray );
384
385 std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths;
386
387 for( auto iter = beginIter; iter != endIter; iter++ )
388 {
389 symbolSheetpaths.push_back( std::pair<SCH_SYMBOL*,
390 SCH_SHEET_PATH>( iter->second.first,
391 iter->second.second ) );
392 }
393
394 std::stable_sort( symbolSheetpaths.begin(), symbolSheetpaths.end(),
396
397 compPackageStruct.m_value = value;
398 compPackageStruct.m_tolerance = tol;
399 compPackageStruct.m_symbolSheetpaths = symbolSheetpaths;
400 compPackageMap.insert( std::pair( deviceType, compPackageStruct ) );
401
402 // Write out the corresponding device file
403 FILE* d = nullptr;
404 wxString deviceFileName = wxFileName( m_exportPath, deviceType,
405 wxString( "txt" ) ).GetFullPath();
406
407 if( ( d = wxFopen( deviceFileName, wxT( "wt" ) ) ) == nullptr )
408 {
409 wxString msg;
410 msg.Printf( _( "Failed to create file '%s'.\n" ), deviceFileName );
411 deviceFileCreatingError += msg;
412 continue;
413 }
414
415 footprintText = footprintText.AfterLast( ':' );
416
417 wxArrayString footprintAlt;
418 wxArrayString footprintArray = sym->GetLibSymbolRef()->GetFPFilters();
419
420 for( const wxString& fp : footprintArray )
421 {
422 if( ( fp.Find( '*' ) != wxNOT_FOUND ) || ( fp.Find( '?' ) != wxNOT_FOUND ) )
423 {
424 continue;
425 }
426
427 footprintAlt.Add( fp.AfterLast( ':' ) );
428 }
429
430 if( footprintText.IsEmpty() )
431 {
432 if( !footprintAlt.IsEmpty() )
433 {
434 footprintText = footprintAlt[0];
435 footprintAlt.RemoveAt( 0 );
436 }
437 else
438 {
439 footprintText = deviceType;
440 }
441 }
442
443 fmt::print( d, "PACKAGE '{}'\n", TO_UTF8( formatDevice( footprintText ) ) );
444 fmt::print( d, "CLASS IC\n" );
445
446 std::vector<SCH_PIN*> pinList = sym->GetLibSymbolRef()->GetPins();
447
448 /*
449 * We must erase redundant Pins references in pinList
450 * These redundant pins exist because some pins are found more than one time when a
451 * symbol has multiple parts per package or has 2 representations (DeMorgan conversion).
452 * For instance, a 74ls00 has DeMorgan conversion, with different pin shapes, and
453 * therefore each pin appears 2 times in the list. Common pins (VCC, GND) can also be
454 * found more than once.
455 */
456 sort( pinList.begin(), pinList.end(), NETLIST_EXPORTER_ALLEGRO::CompareLibPin );
457
458 for( int ii = 0; ii < (int) pinList.size() - 1; ii++ )
459 {
460 if( pinList[ii]->GetNumber() == pinList[ii + 1]->GetNumber() )
461 {
462 // 2 pins have the same number, remove the redundant pin at index i+1
463 pinList.erase( pinList.begin() + ii + 1 );
464 ii--;
465 }
466 }
467
468 unsigned int pinCount = pinList.size();
469 fmt::print( d, "PINCOUNT {}\n", pinCount );
470
471 if( pinCount > 0 )
472 {
473 fmt::print( d, "{}", TO_UTF8( formatFunction( "main", pinList ) ) );
474 }
475
476 if( !value.IsEmpty() )
477 {
478 fmt::print( d, "PACKAGEPROP VALUE {}\n", TO_UTF8( value ) );
479 }
480
481 if( !tol.IsEmpty() )
482 {
483 fmt::print( d, "PACKAGEPROP TOL {}\n", TO_UTF8( tol ) );
484 }
485
486 if( !footprintAlt.IsEmpty() )
487 {
488 fmt::print( d, "PACKAGEPROP ALT_SYMBOLS '({})'\n", fmt::join( footprintAlt, "," ) );
489 }
490
491 wxArrayString propArray;
492 propArray.Add( "PART_NUMBER" );
493 propArray.Add( "mpn" );
494 propArray.Add( "mfr_pn" );
495 wxString data = getGroupField( groupIndex, propArray );
496
497 if(!data.IsEmpty())
498 {
499 fmt::print( d, "PACKAGEPROP {} {}\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
500 }
501
502 propArray.clear();
503 propArray.Add( "HEIGHT" );
504 data = getGroupField( groupIndex, propArray );
505
506 if(!data.IsEmpty())
507 {
508 fmt::print( d, "PACKAGEPROP {} {}\n", TO_UTF8( propArray[0] ), TO_UTF8( data ) );
509 }
510
511 fmt::print( d, "END\n" );
512
513 fclose( d );
514 }
515
516 fmt::print( m_f, "$PACKAGES\n" );
517
518 for( auto iter = compPackageMap.begin(); iter != compPackageMap.end(); iter++ )
519 {
520 wxString deviceType = iter->first;
521 wxString value = iter->second.m_value;
522 wxString tolerance = iter->second.m_tolerance;
523
524 if( value.IsEmpty() && tolerance.IsEmpty() )
525 {
526 fmt::print( m_f, "! '{}' ; ", TO_UTF8( deviceType ) );
527 }
528 else if( tolerance.IsEmpty() )
529 {
530 fmt::print( m_f, "! '{}' ! '{}' ; ", TO_UTF8( deviceType ), TO_UTF8( value ) );
531 }
532 else
533 {
534 fmt::print( m_f, "! '{}' ! '{}' ! {} ; ", TO_UTF8( deviceType ), TO_UTF8( value ),
535 TO_UTF8( tolerance ) );
536 }
537
538 std::vector<std::pair<SCH_SYMBOL*, SCH_SHEET_PATH>> symbolSheetpaths =
539 iter->second.m_symbolSheetpaths;
540
541 std::vector<wxString> refTexts;
542 for( const auto& [ sym, sheetPath ] : symbolSheetpaths)
543 refTexts.push_back( sym->GetRef( &sheetPath ) );
544
545 fmt::print( m_f, "{}", fmt::join( refTexts, ",\n\t" ) );
546
547 fmt::print( m_f, "\n" );
548 }
549
550 if( !deviceFileCreatingError.IsEmpty() )
551 DisplayError( nullptr, deviceFileCreatingError );
552}
553
554
555wxString NETLIST_EXPORTER_ALLEGRO::formatText( wxString aString )
556{
557 if( aString.IsEmpty() )
558 return wxEmptyString;
559
560 aString.Replace( "\u03BC", "u" );
561
562 std::regex reg( "[!']|[^ -~]" );
563 wxString processedString = wxString( std::regex_replace( std::string( aString ), reg, "?" ) );
564
565 std::regex search_reg( "[^a-zA-Z0-9_/]" );
566
567 if( std::regex_search( std::string( processedString ), search_reg ) )
568 return wxString( "'" ) + processedString + wxString( "'" );
569
570 return processedString;
571}
572
573
575{
576 wxString pinName4Telesis = aPin.GetName() + wxString( "__" ) + aPin.GetNumber();
577 std::regex reg( "[^A-Za-z0-9_+?/-]" );
578 return wxString( std::regex_replace( std::string( pinName4Telesis ), reg, "?" ) );
579}
580
581
582wxString NETLIST_EXPORTER_ALLEGRO::formatFunction( wxString aName, std::vector<SCH_PIN*> aPinList )
583{
584 aName.MakeUpper();
585 std::list<wxString> pinNameList;
586
587 std::stable_sort( aPinList.begin(), aPinList.end(), NETLIST_EXPORTER_ALLEGRO::CompareLibPin );
588
589 for( auto pin : aPinList )
590 pinNameList.push_back( formatPin( *pin ) );
591
592 wxString out_str = "";
593 wxString str;
594
595 out_str.Printf( wxT( "PINORDER %s " ), TO_UTF8( aName ) );
596
597 for( const wxString& pinName : pinNameList )
598 {
599 str.Printf( ",\n\t%s", TO_UTF8( pinName ) );
600 out_str += str;
601 }
602 out_str += wxString( "\n" );
603
604 str.Printf( wxT( "FUNCTION %s %s " ), TO_UTF8( aName ), TO_UTF8( aName ) );
605 out_str += str;
606
607 for( auto pin : aPinList )
608 {
609 str.Printf( ",\n\t%s", TO_UTF8( pin->GetNumber() ) );
610 out_str += str;
611 }
612
613 out_str += wxString( "\n" );
614
615 return out_str;
616}
617
618
619wxString NETLIST_EXPORTER_ALLEGRO::getGroupField( int aGroupIndex, const wxArrayString& aFieldArray,
620 bool aSanitize )
621{
622 auto pairIter = m_componentGroups.equal_range( aGroupIndex );
623
624 for( auto iter = pairIter.first; iter != pairIter.second; ++iter )
625 {
626 SCH_SYMBOL* sym = ( iter->second ).first;
627 SCH_SHEET_PATH sheetPath = ( iter->second ).second;
628
629 for( const wxString& field : aFieldArray )
630 {
631 if( SCH_FIELD* fld = sym->FindFieldCaseInsensitive( field ) )
632 {
633 wxString fieldText = fld->GetShownText( &sheetPath, true );
634
635 if( !fieldText.IsEmpty() )
636 {
637 if( aSanitize )
638 return formatText( fieldText );
639 else
640 return fieldText;
641 }
642 }
643 }
644 }
645
646 for( auto iter = pairIter.first; iter != pairIter.second; ++iter )
647 {
648 SCH_SYMBOL* sym = ( iter->second ).first;
649
650 for( const wxString& field : aFieldArray )
651 {
652 if( SCH_FIELD* fld = sym->GetLibSymbolRef()->FindFieldCaseInsensitive( field ) )
653 {
654 wxString fieldText = fld->GetShownText( false, 0 );
655
656 if( !fieldText.IsEmpty() )
657 {
658 if( aSanitize )
659 return formatText( fieldText );
660 else
661 return fieldText;
662 }
663 }
664 }
665 }
666
667 return wxEmptyString;
668}
669
670
671wxString NETLIST_EXPORTER_ALLEGRO::formatDevice( wxString aString )
672{
673 aString.MakeLower();
674 std::regex reg( "[^a-z0-9_-]" );
675 return wxString( std::regex_replace( std::string( aString ), reg, "_" ) );
676}
677
678
680{
681 fmt::print( m_f, "$A_PROPERTIES\n" );
682
683 while( !m_packageProperties.empty() )
684 {
685 std::multimap<wxString, wxString>::iterator iter = m_packageProperties.begin();
686 wxString sheetPathText = iter->first;
687
688 fmt::print( m_f, "'ROOM' '{}' ; ", TO_UTF8( formatText( sheetPathText ) ) );
689
690 std::vector<wxString> refTexts;
691
692 auto pairIter = m_packageProperties.equal_range( sheetPathText );
693
694 for( iter = pairIter.first; iter != pairIter.second; ++iter )
695 {
696 wxString refText = iter->second;
697 refTexts.push_back( refText );
698 }
699
700 m_packageProperties.erase( pairIter.first, pairIter.second );
701
702 std::stable_sort( refTexts.begin(), refTexts.end(),
704
705 fmt::print( m_f, "{}", fmt::join( refTexts, ",\n\t" ) );
706
707 fmt::print( m_f, "\n" );
708 }
709}
710
711
713{
714 fmt::print( m_f, "$NETS\n" );
715
716 while( !m_netNameNodes.empty() )
717 {
718 std::multimap<wxString, NET_NODE>::iterator iter = m_netNameNodes.begin();
719 std::vector<NET_NODE> netNodes;
720
721 wxString netName = iter->first;
722
723 fmt::print( m_f, "{}; ", TO_UTF8( formatText( netName ).MakeUpper() ) );
724
725 auto pairIter = m_netNameNodes.equal_range( netName );
726
727 for( iter = pairIter.first; iter != pairIter.second; ++iter )
728 {
729 NET_NODE netNode = iter->second;
730 netNodes.push_back( netNode );
731 }
732
733 m_netNameNodes.erase( pairIter.first, pairIter.second );
734
735 std::stable_sort( netNodes.begin(), netNodes.end() );
736
737 std::vector<wxString> nets;
738 for( const NET_NODE& netNode : netNodes )
739 {
740 wxString refText = netNode.m_Pin->GetParentSymbol()->GetRef( &netNode.m_Sheet );
741 wxString pinText = netNode.m_Pin->GetShownNumber();
742 nets.push_back( refText + wxString( "." ) + pinText );
743 }
744
745 fmt::print( m_f, "{}", fmt::join( nets, ",\n\t" ) );
746
747 fmt::print( m_f, "\n" );
748 }
749}
750
751
753{
754 while( ( aString.GetChar( aString.Length() - 1 ) >= '0' )
755 && ( aString.GetChar( aString.Length() - 1 ) <= '9' ) )
756 {
757 aString.RemoveLast();
758 }
759
760 return aString;
761}
762
763
764unsigned int NETLIST_EXPORTER_ALLEGRO::extractTailNumber( wxString aString )
765{
766 wxString numString;
767
768 while( ( aString.GetChar( aString.Length() - 1 ) >= '0' )
769 && ( aString.GetChar( aString.Length() - 1 ) <= '9' ) )
770 {
771 numString.insert( 0, aString.GetChar( aString.Length() - 1 ) );
772 aString.RemoveLast();
773 }
774
775 unsigned long val;
776
777 //From wxWidgets 3.1.6, here we can use ToUInt instead of ToULong function.
778 numString.ToULong( &val );
779 return (unsigned int) val;
780}
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
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
wxArrayString GetFPFilters() const
Definition lib_symbol.h:217
std::vector< SCH_PIN * > GetPins() const override
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
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:223
wxString GetShownNumber() const
Definition sch_pin.cpp:587
const wxString & GetName() const
Definition sch_pin.cpp:400
const wxString & GetNumber() const
Definition sch_pin.h:124
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
SCH_FIELD * FindFieldCaseInsensitive(const wxString &aFieldName)
Search for a SCH_FIELD with aFieldName.
const wxString GetFootprintFieldText(bool aResolve, const SCH_SHEET_PATH *aPath, bool aAllowExtraText) const
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
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:192
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 for symbol library class.
@ SCH_NO_CONNECT_T
Definition typeinfo.h:162
@ SCH_SYMBOL_T
Definition typeinfo.h:174
@ SCH_PIN_T
Definition typeinfo.h:155