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