KiCad PCB EDA Suite
drc_test_provider_schematic_parity.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) 2004-2022 KiCad Developers.
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 <board.h>
25#include <pad.h>
26#include <drc/drc_engine.h>
27#include <drc/drc_item.h>
28#include <drc/drc_rule.h>
30
31#include <kiway.h>
33
34/*
35 Schematic parity test.
36
37 Errors generated:
38 - DRCE_MISSING_FOOTPRINT
39 - DRCE_DUPLICATE_FOOTPRINT
40 - DRCE_EXTRA_FOOTPRINT
41
42 TODO:
43 - cross-check PCB netlist against SCH netlist
44 - cross-check PCB fields against SCH fields
45*/
46
48{
49public:
51 {
52 m_isRuleDriven = false;
53 }
54
56 {
57 }
58
59 virtual bool Run() override;
60
61 virtual const wxString GetName() const override
62 {
63 return wxT( "schematic_parity" );
64 };
65
66 virtual const wxString GetDescription() const override
67 {
68 return wxT( "Performs layout-vs-schematics integity check" );
69 }
70
71private:
72 void testNetlist( NETLIST& aNetlist );
73};
74
75
77{
78 BOARD* board = m_drcEngine->GetBoard();
79
80 auto compare = []( const FOOTPRINT* x, const FOOTPRINT* y )
81 {
82 return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
83 };
84
85 auto footprints = std::set<FOOTPRINT*, decltype( compare )>( compare );
86
87 // Search for duplicate footprints on the board
88 for( FOOTPRINT* footprint : board->Footprints() )
89 {
91 break;
92
93 auto ins = footprints.insert( footprint );
94
95 if( !ins.second && !( footprint->GetAttributes() & FP_BOARD_ONLY ) )
96 {
97 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_DUPLICATE_FOOTPRINT );
98 drcItem->SetItems( footprint, *ins.first );
99
100 reportViolation( drcItem, footprint->GetPosition(), UNDEFINED_LAYER );
101 }
102 }
103
104 // Search for component footprints in the netlist but not on the board.
105 for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
106 {
107 COMPONENT* component = aNetlist.GetComponent( ii );
108 FOOTPRINT* footprint = board->FindFootprintByReference( component->GetReference() );
109
110 if( footprint == nullptr )
111 {
113 break;
114
115 wxString msg;
116 msg.Printf( _( "Missing footprint %s (%s)" ),
117 component->GetReference(),
118 component->GetValue() );
119
120 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_FOOTPRINT );
121
122 drcItem->SetErrorMessage( msg );
123 reportViolation( drcItem, wxPoint(), UNDEFINED_LAYER );
124 }
125 else
126 {
127 for( PAD* pad : footprint->Pads() )
128 {
130 break;
131
132 if( !pad->CanHaveNumber() )
133 continue;
134
135 const COMPONENT_NET& sch_net = component->GetNet( pad->GetNumber() );
136 const wxString& pcb_netname = pad->GetNetname();
137
138 if( !pcb_netname.IsEmpty() && sch_net.GetPinName().IsEmpty() )
139 {
140 wxString msg;
141 msg.Printf( _( "No corresponding pin found in schematic." ) );
142
143 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT );
144 drcItem->SetErrorMessage( msg );
145 drcItem->SetItems( pad );
146 reportViolation( drcItem, footprint->GetPosition(), UNDEFINED_LAYER );
147 }
148 else if( pcb_netname.IsEmpty() && !sch_net.GetNetName().IsEmpty() )
149 {
150 wxString msg;
151 msg.Printf( _( "Pad missing net given by schematic (%s)." ),
152 sch_net.GetNetName() );
153
154 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT );
155 drcItem->SetErrorMessage( msg );
156 drcItem->SetItems( pad );
157 reportViolation( drcItem, footprint->GetPosition(), UNDEFINED_LAYER );
158 }
159 else if( pcb_netname != sch_net.GetNetName() )
160 {
161 wxString msg;
162 msg.Printf( _( "Pad net (%s) doesn't match net given by schematic (%s)." ),
163 pcb_netname,
164 sch_net.GetNetName() );
165
166 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT );
167 drcItem->SetErrorMessage( msg );
168 drcItem->SetItems( pad );
169 reportViolation( drcItem, footprint->GetPosition(), UNDEFINED_LAYER );
170 }
171 }
172
173 for( unsigned jj = 0; jj < component->GetNetCount(); ++jj )
174 {
176 break;
177
178 const COMPONENT_NET& sch_net = component->GetNet( jj );
179
180 if( !footprint->FindPadByNumber( sch_net.GetPinName() ) )
181 {
182 wxString msg;
183 msg.Printf( _( "No pad found for pin %s in schematic." ),
184 sch_net.GetPinName() );
185
186 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_NET_CONFLICT );
187 drcItem->SetErrorMessage( msg );
188 drcItem->SetItems( footprint );
189 reportViolation( drcItem, footprint->GetPosition(), UNDEFINED_LAYER );
190 }
191 }
192 }
193 }
194
195 // Search for component footprints found on board but not in netlist.
196 for( FOOTPRINT* footprint : board->Footprints() )
197 {
199 break;
200
201 if( footprint->GetAttributes() & FP_BOARD_ONLY )
202 continue;
203
204 if( !aNetlist.GetComponentByReference( footprint->GetReference() ) )
205 {
206 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_EXTRA_FOOTPRINT );
207
208 drcItem->SetItems( footprint );
209 reportViolation( drcItem, footprint->GetPosition(), UNDEFINED_LAYER );
210 }
211 }
212}
213
214
216{
218 {
219 if( !reportPhase( _( "Checking PCB to schematic parity..." ) ) )
220 return false;
221
223
224 if( !netlist )
225 {
226 reportAux( wxT( "No netlist provided, skipping schematic parity tests." ) );
227 return true;
228 }
229
231
233 }
234
235 return !m_drcEngine->IsCancelled();
236}
237
238
239namespace detail
240{
242}
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
FOOTPRINTS & Footprints()
Definition: board.h:307
FOOTPRINT * FindFootprintByReference(const wxString &aReference) const
Search for a FOOTPRINT within this board with the given reference designator.
Definition: board.cpp:1412
Used to store the component pin name to net name (and pin function) associations stored in a netlist.
Definition: pcb_netlist.h:44
const wxString & GetNetName() const
Definition: pcb_netlist.h:58
const wxString & GetPinName() const
Definition: pcb_netlist.h:57
Store all of the related footprint information found in a netlist.
Definition: pcb_netlist.h:85
const COMPONENT_NET & GetNet(unsigned aIndex) const
Definition: pcb_netlist.h:111
const wxString & GetReference() const
Definition: pcb_netlist.h:126
const wxString & GetValue() const
Definition: pcb_netlist.h:129
unsigned GetNetCount() const
Definition: pcb_netlist.h:109
bool GetTestFootprints() const
Definition: drc_engine.h:163
BOARD * GetBoard() const
Definition: drc_engine.h:89
bool IsErrorLimitExceeded(int error_code)
bool IsCancelled() const
NETLIST * GetSchematicNetlist() const
Definition: drc_engine.h:95
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition: drc_item.cpp:325
virtual const wxString GetName() const override
virtual const wxString GetDescription() const override
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out #DRC_ITEMs and po...
virtual bool reportPhase(const wxString &aStageName)
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer)
virtual void reportAux(wxString fmt,...)
DRC_ENGINE * m_drcEngine
virtual void reportRuleStatistics()
PADS & Pads()
Definition: footprint.h:174
const wxString & GetReference() const
Definition: footprint.h:519
VECTOR2I GetPosition() const override
Definition: footprint.h:192
PAD * FindPadByNumber(const wxString &aPadNumber, PAD *aSearchAfterMe=nullptr) const
Return a PAD with a matching number.
Definition: footprint.cpp:1151
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
Definition: pcb_netlist.h:213
unsigned GetCount() const
Definition: pcb_netlist.h:234
COMPONENT * GetComponentByReference(const wxString &aReference)
Return a COMPONENT by aReference.
COMPONENT * GetComponent(unsigned aIndex)
Return the COMPONENT at aIndex.
Definition: pcb_netlist.h:242
Definition: pad.h:58
@ DRCE_DUPLICATE_FOOTPRINT
Definition: drc_item.h:71
@ DRCE_EXTRA_FOOTPRINT
Definition: drc_item.h:72
@ DRCE_NET_CONFLICT
Definition: drc_item.h:73
@ DRCE_MISSING_FOOTPRINT
Definition: drc_item.h:70
#define _(s)
@ FP_BOARD_ONLY
Definition: footprint.h:71
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy