KiCad PCB EDA Suite
Loading...
Searching...
No Matches
conn_claims.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 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
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include "conn_claims.h"
21
22#include <algorithm>
23#include <tuple>
24
25namespace SCH_CONNECTIVITY
26{
27namespace
28{
29 void SortNames( std::vector<NAME_ID>& aNames, const SESSION_KEYS& aKeys )
30 {
31 std::ranges::sort( aNames, NAME_LESS{ &aKeys } );
32 aNames.erase( std::ranges::unique( aNames ).begin(), aNames.end() );
33 }
34
35 PRIORITY LabelPriority( KICAD_T aType )
36 {
37 switch( aType )
38 {
43 default: return PRIORITY::NONE;
44 }
45 }
46} // namespace
47
48bool CLAIM::operator==( const CLAIM& aOther ) const
49{
52 == std::tie( aOther.priority, aOther.depth, aOther.path, aOther.name, aOther.ncName, aOther.fullName,
53 aOther.source, aOther.globalPowerParent, aOther.localPowerParent, aOther.outputShape,
54 aOther.hasPad, aOther.portInstance )
55 && ( schema == aOther.schema || ( schema && aOther.schema && *schema == *aOther.schema ) );
56}
57
58bool CLAIM_LESS::operator()( const CLAIM& aLeft, const CLAIM& aRight ) const
59{
60 const auto rank = []( const CLAIM& aClaim )
61 {
62 return std::tuple( aClaim.priority, -static_cast<int>( aClaim.depth ), aClaim.globalPowerParent,
63 aClaim.localPowerParent, aClaim.outputShape, !aClaim.hasPad );
64 };
65
66 if( const auto leftRank = rank( aLeft ), rightRank = rank( aRight ); leftRank != rightRank )
67 return leftRank < rightRank;
68
69 if( aLeft.fullName != aRight.fullName )
70 return keys.NameLess( aRight.fullName, aLeft.fullName );
71
72 return keys.Less( aRight.source, aLeft.source );
73}
74
76 const INSTANCE_SCOPE& aScope, SESSION_KEYS& aKeys, BUS_PARSE_CACHE& aParses )
77{
79 result.instance = aScope.instance;
80 std::map<KIID, const ITEM_TEXT_FACT*> text;
81
82 for( const ITEM_TEXT_FACT& item : aText.items )
83 text.emplace( item.id, &item );
84
85 const auto prepare = [&]( const ITEM_FACT& fact, const PIN_FACT* pin, const KIID& id )
86 {
87 const auto found = text.find( id );
88
89 if( pin && found == text.end() )
90 return;
91
92 SOURCE_CLAIMS& input = result.items[id];
93 input.type = fact.type;
94 PRIORITY priority = LabelPriority( fact.type );
95
96 if( pin )
97 {
98 priority = pin->globalPower ? PRIORITY::GLOBAL_POWER_PIN
99 : pin->localPower ? PRIORITY::LOCAL_POWER_PIN
101 input.pinGroup = fact.id;
102 input.pinWitness = !pin->globalPowerParent && !pin->localPowerParent;
103 input.invisiblePower = pin->globalPower && pin->invisible && pin->type == ELECTRICAL_PINTYPE::PT_POWER_IN
104 && !pin->globalPowerParent && !pin->localPowerParent;
105 }
106
107 if( fact.type == SCH_SHEET_PIN_T )
108 {
109 if( auto child = aScope.children.find( fact.owner ); child != aScope.children.end() )
110 input.portInstance = child->second;
111 }
112 else if( fact.type == SCH_HIER_LABEL_T )
113 input.portInstance = aScope.instance;
114
115 if( found == text.end() )
116 return;
117
118 const ITEM_TEXT_FACT& item = *found->second;
119
120 for( const wxString& name : item.netclasses )
121 input.netclasses.push_back( aKeys.InternName( name ) );
122
123 if( !item.canDrive || priority == PRIORITY::NONE )
124 return;
125
126 CLAIM claim;
127 claim.priority = priority;
128 claim.source = { id, aScope.instance };
129 const bool unscoped =
130 priority == PRIORITY::GLOBAL || priority == PRIORITY::GLOBAL_POWER_PIN || priority == PRIORITY::PIN;
131 claim.depth = unscoped ? 0 : aScope.depth;
132 claim.path = aKeys.InternName( unscoped ? wxString() : aScope.path );
133 claim.name = aKeys.InternName( item.name );
134 claim.ncName = aKeys.InternName( item.ncName );
135 claim.fullName = aKeys.InternName( aKeys.Name( claim.path ) + item.name );
136 claim.globalPowerParent = pin && pin->globalPowerParent;
137 claim.localPowerParent = pin && pin->localPowerParent;
138 claim.outputShape = fact.type == SCH_SHEET_PIN_T && fact.outputShape;
139 claim.hasPad = item.name.Contains( wxS( "-Pad" ) );
140 claim.schema = aParses.Parse( item.name ).value.schema;
141
142 if( fact.type == SCH_SHEET_PIN_T )
143 claim.portInstance = input.portInstance;
144
145 input.claim = std::move( claim );
146 };
147
148 for( const ITEM_FACT& fact : aFacts.items )
149 {
150 if( fact.type == SCH_PIN_T )
151 {
152 for( const PIN_FACT& pin : fact.pins )
153 prepare( fact, &pin, pin.id );
154 }
155 else
156 {
157 prepare( fact, nullptr, fact.id );
158 }
159 }
160
161 for( const INSTANCE_RULE_AREA_FACT& area : aText.ruleAreas )
162 {
163 std::vector<NAME_ID> classes;
164
165 for( const wxString& name : area.netclasses )
166 classes.push_back( aKeys.InternName( name ) );
167
168 for( const KIID& id : area.containedItems )
169 {
170 if( auto found = result.items.find( id ); found != result.items.end() )
171 found->second.netclasses.insert( found->second.netclasses.end(), classes.begin(), classes.end() );
172 }
173 }
174
175 for( auto& [id, input] : result.items )
176 SortNames( input.netclasses, aKeys );
177
178 return result;
179}
180
182 const SESSION_KEYS& aKeys )
183{
185 result.items.assign( aIsland.items.begin(), aIsland.items.end() );
186 std::set<KIID> pinGroups;
187 std::vector<KIID> witnesses;
188 bool hasVector = false;
189 bool hasGroup = false;
190 bool hasSignalLabel = false;
191 bool hasBusLabel = false;
192
193 for( const KIID& id : aIsland.items )
194 {
195 const SOURCE_CLAIMS& input = aInputs.items.at( id );
196
197 if( input.claim )
198 {
199 if( input.type == SCH_LABEL_T || input.type == SCH_GLOBAL_LABEL_T || input.type == SCH_HIER_LABEL_T
200 || input.type == SCH_SHEET_PIN_T )
201 {
202 hasBusLabel |= bool( input.claim->schema );
203 hasSignalLabel |= !input.claim->schema;
204 }
205
206 result.claims.push_back( *input.claim );
207
208 if( input.claim->Strong() )
209 result.atoms.strongNames.push_back( input.claim->name );
210
211 if( input.claim->schema )
212 {
213 hasVector |= input.claim->schema->shape == BUS_SCHEMA::SHAPE::VECTOR;
214 hasGroup |= input.claim->schema->shape == BUS_SCHEMA::SHAPE::GROUP;
215 }
216 }
217
218 if( input.type == SCH_PIN_T )
219 {
220 result.atoms.hasSymbolPin = true;
221
222 // Naming counts every pin object while ERC counts merged stacked pins once
223 if( input.pinWitness )
224 {
225 pinGroups.insert( input.pinGroup );
226 witnesses.push_back( id );
227 }
228 }
229 else if( input.type == SCH_NO_CONNECT_T )
230 {
231 if( !result.atoms.noConnect || id < *result.atoms.noConnect )
232 result.atoms.noConnect = id;
233 }
234
235 result.atoms.invisiblePowerWired |= input.invisiblePower && aIsland.hasWire;
236 result.netclasses.insert( result.netclasses.end(), input.netclasses.begin(), input.netclasses.end() );
237 }
238
239 std::sort( result.claims.rbegin(), result.claims.rend(), CLAIM_LESS{ aKeys } );
240 result.kind = ( result.claims.empty() ? aIsland.hasBusLine : bool( result.claims.front().schema ) ) ? KIND::BUNDLE
241 : KIND::SIGNAL;
242 result.atoms.kindConflict = ( aIsland.hasWire && ( aIsland.hasBusLine || result.kind == KIND::BUNDLE ) )
243 || ( aIsland.hasBusLine && result.kind == KIND::SIGNAL )
244 || ( ( aIsland.hasWire || hasSignalLabel ) && hasBusLabel )
245 || ( aIsland.hasBusLine && hasSignalLabel );
246 result.atoms.mixedBusShapes = hasVector && hasGroup;
247 result.atoms.busNoConnect = result.kind == KIND::BUNDLE && result.atoms.noConnect.has_value();
248 result.atoms.pinCount = static_cast<uint32_t>( pinGroups.size() );
249 std::ranges::sort( witnesses, std::less<KIID>() );
250 std::copy_n( witnesses.begin(), std::min( witnesses.size(), result.atoms.pinWitnesses.size() ),
251 result.atoms.pinWitnesses.begin() );
252
253 for( const CLAIM& claim : result.claims )
254 {
255 // Edges are sorted below, so emission order within a claim is irrelevant
256 switch( claim.priority )
257 {
258 case PRIORITY::GLOBAL:
260 result.edges.push_back( { SCOPE::GLOBAL, 0, claim.name } );
261 [[fallthrough]];
264 result.edges.push_back( { SCOPE::SHEET, aInputs.instance, claim.name } );
265 break;
267 result.edges.push_back( { SCOPE::SHEET, aInputs.instance, claim.name } );
268 [[fallthrough]];
270 if( const auto& instance = aInputs.items.at( claim.source.item ).portInstance )
271 result.edges.push_back( { SCOPE::PORT, *instance, claim.name, result.kind } );
272
273 break;
274 default: break;
275 }
276 }
277
278 std::sort( result.edges.begin(), result.edges.end(), KEY_LESS{ aKeys } );
279 result.edges.erase( std::unique( result.edges.begin(), result.edges.end() ), result.edges.end() );
280 SortNames( result.atoms.strongNames, aKeys );
281
282 if( result.claims.empty() )
283 result.netclasses.clear();
284 else
285 SortNames( result.netclasses, aKeys );
286
287 return result;
288}
289} // namespace SCH_CONNECTIVITY
const char * name
Definition kiid.h:46
Parse results for each bus text, with invalidation by alias dependency.
Definition conn_bus.h:130
const ENTRY & Parse(const wxString &aText)
Return the cached entry, and parse again if the entry is missing or dirty.
Definition conn_bus.cpp:234
Session IDs are dense handles, never a canonical ordering.
Definition conn_keys.h:146
const wxString & Name(NAME_ID aId) const
Definition conn_keys.h:163
NAME_ID InternName(const wxString &aText)
Definition conn_keys.h:153
Value keys and the key session of the schematic connectivity engine.
ISLAND_RECORD BuildIslandRecord(const RECORD_GEOMETRY &aIsland, const INSTANCE_CLAIMS &aInputs, const SESSION_KEYS &aKeys)
INSTANCE_CLAIMS PrepareInstanceClaims(const SCREEN_FACTS &aFacts, const INSTANCE_FACTS &aText, const INSTANCE_SCOPE &aScope, SESSION_KEYS &aKeys, BUS_PARSE_CACHE &aParses)
Main-thread interning and parse preparation, followed by a pure per-island fold.
PRIORITY
Driver priority of a claim, from low to high.
Definition conn_claims.h:37
@ SHEET_PIN
Sheet pin. The name belongs to the child instance.
Definition conn_claims.h:40
@ GLOBAL_POWER_PIN
Power input pin of a global power symbol, or a hidden power input pin.
Definition conn_claims.h:45
@ LOCAL_POWER_PIN
Power input pin of a local power symbol.
Definition conn_claims.h:43
@ HIER_LABEL
Hierarchical label. The first strong priority.
Definition conn_claims.h:41
@ NONE
The item makes no claim.
Definition conn_claims.h:38
@ PIN
Symbol pin that is not a power input. The name is "Net-(...)".
Definition conn_claims.h:39
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
Definition pin_type.h:42
@ GROUP
A list such as I2C{SDA SCL}. Members align by name with another group.
Definition conn_bus.h:52
@ VECTOR
A range such as D[0..3]. Members align by ordinal.
Definition conn_bus.h:51
Strict weak order on claims by value.
Definition conn_claims.h:77
const SESSION_KEYS & keys
Definition conn_claims.h:78
bool operator()(const CLAIM &aLeft, const CLAIM &aRight) const
The claim of one item for the name of its island.
Definition conn_claims.h:53
bool globalPowerParent
Pin of a global power symbol.
Definition conn_claims.h:61
bool localPowerParent
Pin of a local power symbol.
Definition conn_claims.h:62
bool operator==(const CLAIM &aOther) const
ITEM_KEY source
The claiming item, the last tie-break.
Definition conn_claims.h:60
bool hasPad
The name contains "-Pad".
Definition conn_claims.h:64
uint16_t depth
Sheet path size, or zero if unscoped.
Definition conn_claims.h:55
std::optional< INST_ID > portInstance
Sheet pin child. Members bind there, not in the parent.
Definition conn_claims.h:66
NAME_ID ncName
Name of an unconnected pin net.
Definition conn_claims.h:58
NAME_ID name
Item text without the sheet prefix.
Definition conn_claims.h:57
bool outputShape
Sheet pin with output shape.
Definition conn_claims.h:63
std::shared_ptr< const BUS_SCHEMA > schema
Parsed bus, or null for a signal.
Definition conn_claims.h:65
NAME_ID path
Sheet prefix, or the empty name if unscoped.
Definition conn_claims.h:56
NAME_ID fullName
path followed by name.
Definition conn_claims.h:59
std::map< KIID, SOURCE_CLAIMS > items
Definition conn_claims.h:97
The text and unit data that one sheet instance resolves for the items of its screen.
Definition conn_facts.h:348
std::vector< INSTANCE_RULE_AREA_FACT > ruleAreas
Definition conn_facts.h:356
std::vector< ITEM_TEXT_FACT > items
Definition conn_facts.h:355
The hierarchy position of one sheet instance.
Definition conn_frame.h:35
std::map< KIID, INST_ID > children
The child instance of each SCH_SHEET KIID on this screen.
Definition conn_frame.h:40
wxString path
The human-readable sheet path, which prefixes scoped names.
Definition conn_frame.h:37
INST_ID instance
The session handle of the instance KIID_PATH.
Definition conn_frame.h:36
uint16_t depth
The number of sheets in the path, with the root sheet as one.
Definition conn_frame.h:38
A value copy of one connectable item, or of one group of pins that share a number and a position.
Definition conn_facts.h:101
KIID id
The item KIID, or the smallest member KIID of a pin group.
Definition conn_facts.h:102
std::vector< PIN_FACT > pins
Definition conn_facts.h:108
KIID owner
The parent symbol or sheet, or niluuid.
Definition conn_facts.h:104
KIID item
The item or pin KIID.
Definition conn_keys.h:78
std::vector< wxString > netclasses
Definition conn_facts.h:269
Orders keys by value through SESSION_KEYS::Less().
Definition conn_keys.h:255
Orders name handles by UTF-8 value.
Definition conn_keys.h:246
Physical inputs to the island record fold.
std::span< const KIID > items
The value copy of one screen.
Definition conn_facts.h:251
std::vector< ITEM_FACT > items
Definition conn_facts.h:256
std::optional< CLAIM > claim
Definition conn_claims.h:89
std::optional< INST_ID > portInstance
Definition conn_claims.h:88
bool pinWitness
Pin whose symbol is not a power symbol.
Definition conn_claims.h:86
std::vector< NAME_ID > netclasses
Definition conn_claims.h:90
KIBIS_PIN * pin
wxString result
Test unit parsing edge cases and error handling.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ SCH_NO_CONNECT_T
Definition typeinfo.h:156
@ SCH_LABEL_T
Definition typeinfo.h:163
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_SHEET_PIN_T
Definition typeinfo.h:170
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164
@ SCH_PIN_T
Definition typeinfo.h:149