KiCad PCB EDA Suite
schematic.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) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <bus_alias.h>
21#include <connection_graph.h>
22#include <erc_settings.h>
23#include <sch_marker.h>
24#include <project.h>
27#include <schematic.h>
28#include <sch_screen.h>
29#include <sim/spice_settings.h>
30
31
33 EDA_ITEM( nullptr, SCHEMATIC_T ),
34 m_project( nullptr ),
35 m_rootSheet( nullptr )
36{
39
40 SetProject( aPrj );
41}
42
43
45{
46 delete m_currentSheet;
47 delete m_connectionGraph;
48}
49
50
52{
53 // Assume project already saved
54 if( m_project )
55 {
57
58 delete project.m_ErcSettings;
59 delete project.m_SchematicSettings;
60
61 project.m_ErcSettings = nullptr;
62 project.m_SchematicSettings = nullptr;
63
64 m_project = nullptr; // clear the project, so we don't do this again when setting a new one
65 }
66
67 delete m_rootSheet;
68
69 m_rootSheet = nullptr;
70
73}
74
75
77{
78 if( m_project )
79 {
81
82 delete project.m_ErcSettings;
83 delete project.m_SchematicSettings;
84
85 project.m_ErcSettings = nullptr;
86 project.m_SchematicSettings = nullptr;
87 }
88
89 m_project = aPrj;
90
91 if( m_project )
92 {
94 project.m_ErcSettings = new ERC_SETTINGS( &project, "erc" );
95 project.m_SchematicSettings = new SCHEMATIC_SETTINGS( &project, "schematic" );
96
97 project.m_SchematicSettings->LoadFromFile();
98 project.m_SchematicSettings->m_NgspiceSimulatorSettings->LoadFromFile();
99 project.m_ErcSettings->LoadFromFile();
100 }
101}
102
103
104void SCHEMATIC::SetRoot( SCH_SHEET* aRootSheet )
105{
106 wxCHECK_RET( aRootSheet, "Call to SetRoot with null SCH_SHEET!" );
107
108 m_rootSheet = aRootSheet;
109
112
114}
115
116
118{
119 return IsValid() ? m_rootSheet->GetScreen() : nullptr;
120}
121
122
123bool SCHEMATIC::ResolveTextVar( wxString* token, int aDepth ) const
124{
125 if( !CurrentSheet().empty() )
126 {
127 if( token->IsSameAs( wxT( "#" ) ) )
128 {
129 *token = CurrentSheet().GetPageNumber();
130 return true;
131 }
132 else if( token->IsSameAs( wxT( "##" ) ) )
133 {
134 *token = wxString::Format( "%i", Root().CountSheets() );
135 return true;
136 }
137 else if( token->IsSameAs( wxT( "SHEETPATH" ) ) )
138 {
139 *token = CurrentSheet().PathHumanReadable();
140 return true;
141 }
142 else if( token->IsSameAs( wxT( "SHEETNAME" ) ) )
143 {
144 *token = CurrentSheet().Last()->GetName();
145 return true;
146 }
147 else if( token->IsSameAs( wxT( "FILENAME" ) ) )
148 {
149 wxFileName fn( GetFileName() );
150 *token = fn.GetFullName();
151 return true;
152 }
153 else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) )
154 {
155 *token = Prj().GetProjectName();
156 return true;
157 }
158
160 }
161
162 return false;
163}
164
165
167{
168 return IsValid() ? m_rootSheet->GetScreen()->GetFileName() : wxString( wxEmptyString );
169}
170
171
173{
174 wxASSERT( m_project );
176}
177
178
180{
181 wxASSERT( m_project );
183}
184
185
186std::vector<SCH_MARKER*> SCHEMATIC::ResolveERCExclusions()
187{
188 SCH_SHEET_LIST sheetList = GetSheets();
189 ERC_SETTINGS& settings = ErcSettings();
190
191 for( const SCH_SHEET_PATH& sheet : sheetList )
192 {
193 for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_MARKER_T ) )
194 {
195 SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
196 auto it = settings.m_ErcExclusions.find( marker->Serialize() );
197
198 if( it != settings.m_ErcExclusions.end() )
199 {
200 marker->SetExcluded( true );
201 settings.m_ErcExclusions.erase( it );
202 }
203 }
204 }
205
206 std::vector<SCH_MARKER*> newMarkers;
207
208 for( const wxString& exclusionData : settings.m_ErcExclusions )
209 {
210 SCH_MARKER* marker = SCH_MARKER::Deserialize( exclusionData );
211
212 if( marker )
213 {
214 marker->SetExcluded( true );
215 newMarkers.push_back( marker );
216 }
217 }
218
219 settings.m_ErcExclusions.clear();
220
221 return newMarkers;
222}
223
224
225std::shared_ptr<BUS_ALIAS> SCHEMATIC::GetBusAlias( const wxString& aLabel ) const
226{
227 for( const SCH_SHEET_PATH& sheet : GetSheets() )
228 {
229 for( const std::shared_ptr<BUS_ALIAS>& alias : sheet.LastScreen()->GetBusAliases() )
230 {
231 if( alias->GetName() == aLabel )
232 return alias;
233 }
234 }
235
236 return nullptr;
237}
238
239
241{
242 std::set<wxString> names;
243
244 for( const auto& [ key, subgraphList ] : m_connectionGraph->GetNetMap() )
245 {
246 CONNECTION_SUBGRAPH* firstSubgraph = subgraphList[0];
247
248 if( !firstSubgraph->m_driver_connection->IsBus()
250 {
251 names.insert( key.Name );
252 }
253 }
254
255 return names;
256}
257
258
259bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
260{
261 SCH_SHEET_LIST sheetList = GetSheets();
262 wxString remainder;
263 wxString ref = token->BeforeFirst( ':', &remainder );
264 SCH_SHEET_PATH sheetPath;
265 SCH_ITEM* refItem = sheetList.GetItem( KIID( ref ), &sheetPath );
266
267 if( refItem && refItem->Type() == SCH_SYMBOL_T )
268 {
269 SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
270
271 if( refSymbol->ResolveTextVar( &remainder, aDepth + 1 ) )
272 *token = remainder;
273 else
274 *token = refSymbol->GetRef( &sheetPath, true ) + ":" + remainder;
275
276 return true; // Cross-reference is resolved whether or not the actual textvar was
277 }
278 else if( refItem && refItem->Type() == SCH_SHEET_T )
279 {
280 SCH_SHEET* refSheet = static_cast<SCH_SHEET*>( refItem );
281
282 if( refSheet->ResolveTextVar( &remainder, aDepth + 1 ) )
283 *token = remainder;
284
285 return true; // Cross-reference is resolved whether or not the actual textvar was
286 }
287
288 return false;
289}
290
291
292std::map<int, wxString> SCHEMATIC::GetVirtualPageToSheetNamesMap() const
293{
294 std::map<int, wxString> namesMap;
295
296 for( const SCH_SHEET_PATH& sheet : GetSheets() )
297 {
298 if( sheet.size() == 1 )
299 namesMap[sheet.GetVirtualPageNumber()] = _( "<root sheet>" );
300 else
301 namesMap[sheet.GetVirtualPageNumber()] = sheet.Last()->GetName();
302 }
303
304 return namesMap;
305}
306
307
308std::map<int, wxString> SCHEMATIC::GetVirtualPageToSheetPagesMap() const
309{
310 std::map<int, wxString> pagesMap;
311
312 for( const SCH_SHEET_PATH& sheet : GetSheets() )
313 pagesMap[sheet.GetVirtualPageNumber()] = sheet.GetPageNumber();
314
315 return pagesMap;
316}
317
318
319wxString SCHEMATIC::ConvertRefsToKIIDs( const wxString& aSource ) const
320{
321 wxString newbuf;
322 size_t sourceLen = aSource.length();
323
324 for( size_t i = 0; i < sourceLen; ++i )
325 {
326 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
327 {
328 wxString token;
329 bool isCrossRef = false;
330 int nesting = 0;
331
332 for( i = i + 2; i < sourceLen; ++i )
333 {
334 if( aSource[i] == '{'
335 && ( aSource[i-1] == '_' || aSource[i-1] == '^' || aSource[i-1] == '~' ) )
336 {
337 nesting++;
338 }
339
340 if( aSource[i] == '}' )
341 {
342 nesting--;
343
344 if( nesting < 0 )
345 break;
346 }
347
348 if( aSource[i] == ':' )
349 isCrossRef = true;
350
351 token.append( aSource[i] );
352 }
353
354 if( isCrossRef )
355 {
356 SCH_SHEET_LIST sheetList = GetSheets();
357 wxString remainder;
358 wxString ref = token.BeforeFirst( ':', &remainder );
359 SCH_REFERENCE_LIST references;
360
361 sheetList.GetSymbols( references );
362
363 for( size_t jj = 0; jj < references.GetCount(); jj++ )
364 {
365 SCH_SYMBOL* refSymbol = references[ jj ].GetSymbol();
366
367 if( ref == refSymbol->GetRef( &references[ jj ].GetSheetPath(), true ) )
368 {
369 token = refSymbol->m_Uuid.AsString() + ":" + remainder;
370 break;
371 }
372 }
373 }
374
375 newbuf.append( "${" + token + "}" );
376 }
377 else
378 {
379 newbuf.append( aSource[i] );
380 }
381 }
382
383 return newbuf;
384}
385
386
387wxString SCHEMATIC::ConvertKIIDsToRefs( const wxString& aSource ) const
388{
389 wxString newbuf;
390 size_t sourceLen = aSource.length();
391
392 for( size_t i = 0; i < sourceLen; ++i )
393 {
394 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
395 {
396 wxString token;
397 bool isCrossRef = false;
398
399 for( i = i + 2; i < sourceLen; ++i )
400 {
401 if( aSource[i] == '}' )
402 break;
403
404 if( aSource[i] == ':' )
405 isCrossRef = true;
406
407 token.append( aSource[i] );
408 }
409
410 if( isCrossRef )
411 {
412 SCH_SHEET_LIST sheetList = GetSheets();
413 wxString remainder;
414 wxString ref = token.BeforeFirst( ':', &remainder );
415
416 SCH_SHEET_PATH refSheetPath;
417 SCH_ITEM* refItem = sheetList.GetItem( KIID( ref ), &refSheetPath );
418
419 if( refItem && refItem->Type() == SCH_SYMBOL_T )
420 {
421 SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
422 token = refSymbol->GetRef( &refSheetPath, true ) + ":" + remainder;
423 }
424 }
425
426 newbuf.append( "${" + token + "}" );
427 }
428 else
429 {
430 newbuf.append( aSource[i] );
431 }
432 }
433
434 return newbuf;
435}
436
437
439{
440 static SCH_SHEET_LIST hierarchy;
441
442 hierarchy.clear();
443 hierarchy.BuildSheetList( m_rootSheet, false );
444
445 return hierarchy;
446}
447
448
450{
451 SCH_SCREENS screens( m_rootSheet );
452
454}
Calculates the connectivity of a schematic and generates netlists.
const NET_MAP & GetNetMap() const
A subgraph is a set of items that are electrically connected on a single sheet.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
SCH_CONNECTION * m_driver_connection
Cache for driver connection.
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:492
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
Container for ERC settings.
Definition: erc_settings.h:109
std::set< wxString > m_ErcExclusions
Definition: erc_settings.h:169
Definition: kiid.h:47
wxString AsString() const
Definition: kiid.cpp:249
void SetExcluded(bool aExcluded)
Definition: marker_base.h:98
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:65
ERC_SETTINGS * m_ErcSettings
Eeschema params.
Definition: project_file.h:127
SCHEMATIC_SETTINGS * m_SchematicSettings
Definition: project_file.h:130
Container for project specific data.
Definition: project.h:63
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:131
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:148
These settings were stored in SCH_BASE_FRAME previously.
void Reset()
Initialize this schematic to a blank one, unloading anything existing.
Definition: schematic.cpp:51
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
Definition: schematic.cpp:449
CONNECTION_GRAPH * m_connectionGraph
Holds and calculates connectivity information of this schematic.
Definition: schematic.h:203
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:119
SCH_SHEET_PATH * m_currentSheet
The sheet path of the sheet currently being edited or displayed.
Definition: schematic.h:200
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: schematic.cpp:123
virtual ~SCHEMATIC()
Definition: schematic.cpp:44
std::shared_ptr< BUS_ALIAS > GetBusAlias(const wxString &aLabel) const
Return a pointer to a bus alias object for the given label, or null if one doesn't exist.
Definition: schematic.cpp:225
std::vector< SCH_MARKER * > ResolveERCExclusions()
Definition: schematic.cpp:186
wxString GetFileName() const override
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:166
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:172
wxString ConvertKIIDsToRefs(const wxString &aSource) const
Definition: schematic.cpp:387
SCH_SHEET_LIST & GetFullHierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:438
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:85
wxString ConvertRefsToKIIDs(const wxString &aSource) const
Definition: schematic.cpp:319
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:104
void SetProject(PROJECT *aPrj)
Definition: schematic.cpp:76
std::map< int, wxString > GetVirtualPageToSheetPagesMap() const
Definition: schematic.cpp:308
PROJECT * m_project
Definition: schematic.h:189
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:117
SCHEMATIC(PROJECT *aPrj)
Definition: schematic.cpp:32
std::set< wxString > GetNetClassAssignmentCandidates()
Return the set of netname candidates for netclass assignment.
Definition: schematic.cpp:240
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:106
SCH_SHEET & Root() const
Definition: schematic.h:90
std::map< int, wxString > GetVirtualPageToSheetNamesMap() const
Definition: schematic.cpp:292
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:75
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
Definition: schematic.cpp:259
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:179
SCH_SHEET * m_rootSheet
The top-level sheet in this schematic hierarchy (or potentially the only one)
Definition: schematic.h:192
bool IsBus() const
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
wxString Serialize() const
Definition: sch_marker.cpp:73
static SCH_MARKER * Deserialize(const wxString &data)
Definition: sch_marker.cpp:84
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
size_t GetCount() const
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:613
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
const wxString & GetFileName() const
Definition: sch_screen.h:143
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:154
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
SCH_ITEM * GetItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr) const
Fetch a SCH_ITEM by ID.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, bool aIncludePowerSymbols=true, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
void BuildSheetList(SCH_SHEET *aSheet, bool aCheckIntegrity)
Build the list of sheets and their sheet path from aSheet.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SCREEN * LastScreen()
wxString GetPageNumber() const
wxString PathHumanReadable(bool aUseShortRootName=true) const
Return the sheet path in a human readable form made from the sheet names.
SCH_SHEET * Last() const
Return a pointer to the last SCH_SHEET of the list.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
void clear()
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:55
wxString GetName() const
Definition: sch_sheet.h:101
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
Definition: sch_sheet.cpp:233
Schematic symbol object.
Definition: sch_symbol.h:80
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:632
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
bool TextVarResolver(wxString *aToken, const PROJECT *aProject) const
Definition: title_block.cpp:95
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
@ SCH_SYMBOL_T
Definition: typeinfo.h:155
@ SCH_SHEET_T
Definition: typeinfo.h:157
@ SCH_MARKER_T
Definition: typeinfo.h:140
@ SCHEMATIC_T
Definition: typeinfo.h:187