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-2021 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>
25 #include <project/project_file.h>
26 #include <project/net_settings.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 {
38  m_connectionGraph = new CONNECTION_GRAPH( this );
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 
104 void 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 
123 bool 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( "SHEETNAME" ) ) )
138  {
139  *token = CurrentSheet().PathHumanReadable();
140  return true;
141  }
142  else if( token->IsSameAs( wxT( "FILENAME" ) ) )
143  {
144  wxFileName fn( GetFileName() );
145  *token = fn.GetFullName();
146  return true;
147  }
148  else if( token->IsSameAs( wxT( "PROJECTNAME" ) ) )
149  {
150  *token = Prj().GetProjectName();
151  return true;
152  }
153 
155  }
156 
157  return false;
158 }
159 
160 
161 wxString SCHEMATIC::GetFileName() const
162 {
163  return IsValid() ? m_rootSheet->GetScreen()->GetFileName() : wxString( wxEmptyString );
164 }
165 
166 
168 {
169  wxASSERT( m_project );
171 }
172 
173 
175 {
176  wxASSERT( m_project );
178 }
179 
180 
181 std::vector<SCH_MARKER*> SCHEMATIC::ResolveERCExclusions()
182 {
183  SCH_SHEET_LIST sheetList = GetSheets();
184  ERC_SETTINGS& settings = ErcSettings();
185 
186  for( const SCH_SHEET_PATH& sheet : sheetList )
187  {
188  for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_MARKER_T ) )
189  {
190  SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
191  auto it = settings.m_ErcExclusions.find( marker->Serialize() );
192 
193  if( it != settings.m_ErcExclusions.end() )
194  {
195  marker->SetExcluded( true );
196  settings.m_ErcExclusions.erase( it );
197  }
198  }
199  }
200 
201  std::vector<SCH_MARKER*> newMarkers;
202 
203  for( const wxString& exclusionData : settings.m_ErcExclusions )
204  {
205  SCH_MARKER* marker = SCH_MARKER::Deserialize( exclusionData );
206 
207  if( marker )
208  {
209  marker->SetExcluded( true );
210  newMarkers.push_back( marker );
211  }
212  }
213 
214  settings.m_ErcExclusions.clear();
215 
216  return newMarkers;
217 }
218 
219 
220 std::shared_ptr<BUS_ALIAS> SCHEMATIC::GetBusAlias( const wxString& aLabel ) const
221 {
222  for( const auto& sheet : GetSheets() )
223  {
224  for( const auto& alias : sheet.LastScreen()->GetBusAliases() )
225  {
226  if( alias->GetName() == aLabel )
227  return alias;
228  }
229  }
230 
231  return nullptr;
232 }
233 
234 
236 {
237  std::vector<wxString> names;
238 
239  // Key is a NET_NAME_CODE aka std::pair<name, code>
240  for( const NET_MAP::value_type& pair: m_connectionGraph->GetNetMap() )
241  {
242  CONNECTION_SUBGRAPH* subgraph = pair.second[0];
243 
245  names.emplace_back( pair.first.first );
246  }
247 
248  return names;
249 }
250 
251 
252 bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
253 {
254  SCH_SHEET_LIST sheetList = GetSheets();
255  wxString remainder;
256  wxString ref = token->BeforeFirst( ':', &remainder );
257  SCH_SHEET_PATH sheetPath;
258  SCH_ITEM* refItem = sheetList.GetItem( KIID( ref ), &sheetPath );
259 
260  if( refItem && refItem->Type() == SCH_SYMBOL_T )
261  {
262  SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
263 
264  if( refSymbol->ResolveTextVar( &remainder, aDepth + 1 ) )
265  *token = remainder;
266  else
267  *token = refSymbol->GetRef( &sheetPath, true ) + ":" + remainder;
268 
269  return true; // Cross-reference is resolved whether or not the actual textvar was
270  }
271  else if( refItem && refItem->Type() == SCH_SHEET_T )
272  {
273  SCH_SHEET* refSheet = static_cast<SCH_SHEET*>( refItem );
274 
275  if( refSheet->ResolveTextVar( &remainder, aDepth + 1 ) )
276  *token = remainder;
277 
278  return true; // Cross-reference is resolved whether or not the actual textvar was
279  }
280 
281  return false;
282 }
283 
284 
285 wxString SCHEMATIC::ConvertRefsToKIIDs( const wxString& aSource ) const
286 {
287  wxString newbuf;
288  size_t sourceLen = aSource.length();
289 
290  for( size_t i = 0; i < sourceLen; ++i )
291  {
292  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
293  {
294  wxString token;
295  bool isCrossRef = false;
296 
297  for( i = i + 2; i < sourceLen; ++i )
298  {
299  if( aSource[i] == '}' )
300  break;
301 
302  if( aSource[i] == ':' )
303  isCrossRef = true;
304 
305  token.append( aSource[i] );
306  }
307 
308  if( isCrossRef )
309  {
310  SCH_SHEET_LIST sheetList = GetSheets();
311  wxString remainder;
312  wxString ref = token.BeforeFirst( ':', &remainder );
313  SCH_REFERENCE_LIST references;
314 
315  sheetList.GetSymbols( references );
316 
317  for( size_t jj = 0; jj < references.GetCount(); jj++ )
318  {
319  SCH_SYMBOL* refSymbol = references[ jj ].GetSymbol();
320 
321  if( ref == refSymbol->GetRef( &references[ jj ].GetSheetPath(), true ) )
322  {
323  token = refSymbol->m_Uuid.AsString() + ":" + remainder;
324  break;
325  }
326  }
327  }
328 
329  newbuf.append( "${" + token + "}" );
330  }
331  else
332  {
333  newbuf.append( aSource[i] );
334  }
335  }
336 
337  return newbuf;
338 }
339 
340 
341 wxString SCHEMATIC::ConvertKIIDsToRefs( const wxString& aSource ) const
342 {
343  wxString newbuf;
344  size_t sourceLen = aSource.length();
345 
346  for( size_t i = 0; i < sourceLen; ++i )
347  {
348  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
349  {
350  wxString token;
351  bool isCrossRef = false;
352 
353  for( i = i + 2; i < sourceLen; ++i )
354  {
355  if( aSource[i] == '}' )
356  break;
357 
358  if( aSource[i] == ':' )
359  isCrossRef = true;
360 
361  token.append( aSource[i] );
362  }
363 
364  if( isCrossRef )
365  {
366  SCH_SHEET_LIST sheetList = GetSheets();
367  wxString remainder;
368  wxString ref = token.BeforeFirst( ':', &remainder );
369 
370  SCH_SHEET_PATH refSheetPath;
371  SCH_ITEM* refItem = sheetList.GetItem( KIID( ref ), &refSheetPath );
372 
373  if( refItem && refItem->Type() == SCH_SYMBOL_T )
374  {
375  SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
376  token = refSymbol->GetRef( &refSheetPath, true ) + ":" + remainder;
377  }
378  }
379 
380  newbuf.append( "${" + token + "}" );
381  }
382  else
383  {
384  newbuf.append( aSource[i] );
385  }
386  }
387 
388  return newbuf;
389 }
390 
391 
393 {
394  static SCH_SHEET_LIST hierarchy;
395 
396  hierarchy.clear();
397  hierarchy.BuildSheetList( m_rootSheet, false );
398  hierarchy.SortByPageNumbers();
399 
400  return hierarchy;
401 }
std::vector< SCH_MARKER * > ResolveERCExclusions()
Definition: schematic.cpp:181
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
virtual ~SCHEMATIC()
Definition: schematic.cpp:44
const wxString & GetFileName() const
Definition: sch_screen.h:137
Container for project specific data.
Definition: project.h:62
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.
SCH_SHEET_PATH * m_currentSheet
The sheet path of the sheet currently being edited or displayed.
Definition: schematic.h:191
SCHEMATIC(PROJECT *aPrj)
Definition: schematic.cpp:32
Calculates the connectivity of a schematic and generates netlists.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
wxString PathHumanReadable(bool aUseShortRootName=true) const
Return the sheet path in a human readable form made from the sheet names.
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:145
SCHEMATIC_SETTINGS & Settings() const
Definition: schematic.cpp:167
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
bool IsValid() const
A simple test if the schematic is loaded, not a complete one.
Definition: schematic.h:108
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the symbol.
Definition: sch_symbol.cpp:933
wxString AsString() const
Definition: kiid.cpp:218
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:142
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:432
CONNECTION_GRAPH * m_connectionGraph
Holds and calculates connectivity information of this schematic.
Definition: schematic.h:194
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
A subgraph is a set of items that are electrically connected on a single sheet.
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:64
std::set< wxString > m_ErcExclusions
Definition: erc_settings.h:167
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:104
Definition: kiid.h:44
void SetExcluded(bool aExcluded)
Definition: marker_base.h:95
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:220
wxString ConvertRefsToKIIDs(const wxString &aSource) const
Definition: schematic.cpp:285
bool ResolveTextVar(wxString *token, int aDepth) const
Definition: schematic.cpp:123
wxString GetPageNumber() const
void BuildSheetList(SCH_SHEET *aSheet, bool aCheckIntegrity)
Build the list of sheets and their sheet path from aSheet.
const NET_MAP & GetNetMap() const
bool ResolveCrossReference(wxString *token, int aDepth) const
Resolves text vars that refer to other items.
Definition: schematic.cpp:252
size_t GetCount() const
PROJECT * m_project
Definition: schematic.h:180
ERC_SETTINGS * m_ErcSettings
Eeschema params.
Definition: project_file.h:125
SCHEMATIC_SETTINGS * m_SchematicSettings
Definition: project_file.h:128
wxString GetFileName() const override
Helper to retrieve the filename from the root sheet screen.
Definition: schematic.cpp:161
Container for ERC settings.
Definition: erc_settings.h:106
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
wxString Serialize() const
Definition: sch_marker.cpp:66
void SetProject(PROJECT *aPrj)
Definition: schematic.cpp:76
void clear()
Forwarded method from std::vector.
SCH_SHEET * m_rootSheet
The top-level sheet in this schematic hierarchy (or potentially the only one)
Definition: schematic.h:183
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
PROJECT & Prj() const override
Return a reference to the project this schematic is part of.
Definition: schematic.h:75
const KIID m_Uuid
Definition: eda_item.h:475
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_ITEM * GetItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr) const
Fetch a SCH_ITEM by ID.
wxString ConvertKIIDsToRefs(const wxString &aSource) const
Definition: schematic.cpp:341
void Reset()
Initialize this schematic to a blank one, unloading anything existing.
Definition: schematic.cpp:51
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
SCH_SHEET & Root() const
Definition: schematic.h:92
Schematic symbol object.
Definition: sch_symbol.h:78
SCH_SCREEN * LastScreen()
void SortByPageNumbers(bool aUpdateVirtualPageNums=true)
Sort the list of sheets by page number.
static bool empty(const wxTextEntryBase *aCtrl)
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
These settings were stored in SCH_BASE_FRAME previously.
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:128
bool TextVarResolver(wxString *aToken, const PROJECT *aProject) const
Definition: title_block.cpp:91
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the sheet.
Definition: sch_sheet.cpp:211
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:174
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:117
SCH_SHEET_PATH & CurrentSheet() const override
Definition: schematic.h:121
std::vector< wxString > GetNetClassAssignmentCandidates()
Return a list of name candidates for netclass assignment.
Definition: schematic.cpp:235
static SCH_MARKER * Deserialize(const wxString &data)
Definition: sch_marker.cpp:77
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:197
SCH_SHEET_LIST & GetFullHierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:392
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113