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 
244  if( !subgraph->m_driver_connection->IsBus()
246  {
247  names.emplace_back( pair.first.first );
248  }
249  }
250 
251  return names;
252 }
253 
254 
255 bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
256 {
257  SCH_SHEET_LIST sheetList = GetSheets();
258  wxString remainder;
259  wxString ref = token->BeforeFirst( ':', &remainder );
260  SCH_SHEET_PATH sheetPath;
261  SCH_ITEM* refItem = sheetList.GetItem( KIID( ref ), &sheetPath );
262 
263  if( refItem && refItem->Type() == SCH_SYMBOL_T )
264  {
265  SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
266 
267  if( refSymbol->ResolveTextVar( &remainder, aDepth + 1 ) )
268  *token = remainder;
269  else
270  *token = refSymbol->GetRef( &sheetPath, true ) + ":" + remainder;
271 
272  return true; // Cross-reference is resolved whether or not the actual textvar was
273  }
274  else if( refItem && refItem->Type() == SCH_SHEET_T )
275  {
276  SCH_SHEET* refSheet = static_cast<SCH_SHEET*>( refItem );
277 
278  if( refSheet->ResolveTextVar( &remainder, aDepth + 1 ) )
279  *token = remainder;
280 
281  return true; // Cross-reference is resolved whether or not the actual textvar was
282  }
283 
284  return false;
285 }
286 
287 
288 wxString SCHEMATIC::ConvertRefsToKIIDs( const wxString& aSource ) const
289 {
290  wxString newbuf;
291  size_t sourceLen = aSource.length();
292 
293  for( size_t i = 0; i < sourceLen; ++i )
294  {
295  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
296  {
297  wxString token;
298  bool isCrossRef = false;
299 
300  for( i = i + 2; i < sourceLen; ++i )
301  {
302  if( aSource[i] == '}' )
303  break;
304 
305  if( aSource[i] == ':' )
306  isCrossRef = true;
307 
308  token.append( aSource[i] );
309  }
310 
311  if( isCrossRef )
312  {
313  SCH_SHEET_LIST sheetList = GetSheets();
314  wxString remainder;
315  wxString ref = token.BeforeFirst( ':', &remainder );
316  SCH_REFERENCE_LIST references;
317 
318  sheetList.GetSymbols( references );
319 
320  for( size_t jj = 0; jj < references.GetCount(); jj++ )
321  {
322  SCH_SYMBOL* refSymbol = references[ jj ].GetSymbol();
323 
324  if( ref == refSymbol->GetRef( &references[ jj ].GetSheetPath(), true ) )
325  {
326  token = refSymbol->m_Uuid.AsString() + ":" + remainder;
327  break;
328  }
329  }
330  }
331 
332  newbuf.append( "${" + token + "}" );
333  }
334  else
335  {
336  newbuf.append( aSource[i] );
337  }
338  }
339 
340  return newbuf;
341 }
342 
343 
344 wxString SCHEMATIC::ConvertKIIDsToRefs( const wxString& aSource ) const
345 {
346  wxString newbuf;
347  size_t sourceLen = aSource.length();
348 
349  for( size_t i = 0; i < sourceLen; ++i )
350  {
351  if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
352  {
353  wxString token;
354  bool isCrossRef = false;
355 
356  for( i = i + 2; i < sourceLen; ++i )
357  {
358  if( aSource[i] == '}' )
359  break;
360 
361  if( aSource[i] == ':' )
362  isCrossRef = true;
363 
364  token.append( aSource[i] );
365  }
366 
367  if( isCrossRef )
368  {
369  SCH_SHEET_LIST sheetList = GetSheets();
370  wxString remainder;
371  wxString ref = token.BeforeFirst( ':', &remainder );
372 
373  SCH_SHEET_PATH refSheetPath;
374  SCH_ITEM* refItem = sheetList.GetItem( KIID( ref ), &refSheetPath );
375 
376  if( refItem && refItem->Type() == SCH_SYMBOL_T )
377  {
378  SCH_SYMBOL* refSymbol = static_cast<SCH_SYMBOL*>( refItem );
379  token = refSymbol->GetRef( &refSheetPath, true ) + ":" + remainder;
380  }
381  }
382 
383  newbuf.append( "${" + token + "}" );
384  }
385  else
386  {
387  newbuf.append( aSource[i] );
388  }
389  }
390 
391  return newbuf;
392 }
393 
394 
396 {
397  static SCH_SHEET_LIST hierarchy;
398 
399  hierarchy.clear();
400  hierarchy.BuildSheetList( m_rootSheet, false );
401  hierarchy.SortByPageNumbers();
402 
403  return hierarchy;
404 }
std::vector< SCH_MARKER * > ResolveERCExclusions()
Definition: schematic.cpp:181
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
SCH_CONNECTION * m_driver_connection
Cache for driver connection.
virtual ~SCHEMATIC()
Definition: schematic.cpp:44
const wxString & GetFileName() const
Definition: sch_screen.h:145
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:942
wxString AsString() const
Definition: kiid.cpp:218
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:156
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const
Return the reference for the given sheet path.
Definition: sch_symbol.cpp:441
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:288
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:255
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:344
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:210
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
bool IsBus() const
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:182
SCH_SHEET_LIST & GetFullHierarchy() const
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:395
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113