1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
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 <footprint.h>
26 #include <macros.h>
27 #include <pad.h>
28 #include <pcb_track.h>
29 #include <zone.h>
30 #include <netinfo.h>
31 #include <wx/log.h>
32
33
34 // Constructor and destructor
NETINFO_LIST(BOARD * aParent)35 NETINFO_LIST::NETINFO_LIST( BOARD* aParent ) :
36 m_parent( aParent )
37 {
38 // Make sure that the unconnected net has number 0
39 AppendNet( new NETINFO_ITEM( aParent, wxEmptyString, 0 ) );
40
41 m_newNetCode = 0;
42 }
43
44
~NETINFO_LIST()45 NETINFO_LIST::~NETINFO_LIST()
46 {
47 clear();
48 }
49
50
clear()51 void NETINFO_LIST::clear()
52 {
53 NETNAMES_MAP::iterator it, itEnd;
54 for( it = m_netNames.begin(), itEnd = m_netNames.end(); it != itEnd; ++it )
55 delete it->second;
56
57 m_netNames.clear();
58 m_netCodes.clear();
59 m_newNetCode = 0;
60 }
61
62
GetNetItem(int aNetCode) const63 NETINFO_ITEM* NETINFO_LIST::GetNetItem( int aNetCode ) const
64 {
65 NETCODES_MAP::const_iterator result = m_netCodes.find( aNetCode );
66
67 if( result != m_netCodes.end() )
68 return (*result).second;
69
70 return nullptr;
71 }
72
73
GetNetItem(const wxString & aNetName) const74 NETINFO_ITEM* NETINFO_LIST::GetNetItem( const wxString& aNetName ) const
75 {
76 NETNAMES_MAP::const_iterator result = m_netNames.find( aNetName );
77
78 if( result != m_netNames.end() )
79 return (*result).second;
80
81 return nullptr;
82 }
83
84
RemoveNet(NETINFO_ITEM * aNet)85 void NETINFO_LIST::RemoveNet( NETINFO_ITEM* aNet )
86 {
87 bool removed = false;
88
89 for( NETCODES_MAP::iterator i = m_netCodes.begin(); i != m_netCodes.end(); ++i )
90 {
91 if ( i->second == aNet )
92 {
93 removed = true;
94 m_netCodes.erase(i);
95 break;
96 }
97 }
98
99 for( NETNAMES_MAP::iterator i = m_netNames.begin(); i != m_netNames.end(); ++i )
100 {
101 if ( i->second == aNet )
102 {
103 wxASSERT_MSG( removed, "NETINFO_LIST::RemoveNet: target net found in m_netNames "
104 "but not m_netCodes!" );
105 m_netNames.erase(i);
106 break;
107 }
108 }
109
110 if( removed )
111 m_newNetCode = std::min( m_newNetCode, aNet->m_netCode - 1 );
112 }
113
114
RemoveUnusedNets()115 void NETINFO_LIST::RemoveUnusedNets()
116 {
117 NETCODES_MAP existingNets = m_netCodes;
118
119 m_netCodes.clear();
120 m_netNames.clear();
121
122 for( std::pair<const int, NETINFO_ITEM*> item : existingNets )
123 {
124 if( item.second->IsCurrent() )
125 {
126 m_netNames.insert( std::make_pair( item.second->GetNetname(), item.second ) );
127 m_netCodes.insert( std::make_pair( item.first, item.second ) );
128 }
129 }
130 }
131
132
AppendNet(NETINFO_ITEM * aNewElement)133 void NETINFO_LIST::AppendNet( NETINFO_ITEM* aNewElement )
134 {
135 // if there is a net with such name then just assign the correct number
136 NETINFO_ITEM* sameName = GetNetItem( aNewElement->GetNetname() );
137
138 if( sameName != nullptr )
139 {
140 aNewElement->m_netCode = sameName->GetNetCode();
141
142 return;
143 }
144 else if( aNewElement->m_netCode != (int) m_netCodes.size() || aNewElement->m_netCode < 0 )
145 {
146 // be sure that net codes are consecutive
147 // negative net code means that it has to be auto assigned
148 aNewElement->m_netCode = getFreeNetCode();
149 }
150
151 // net names & codes are supposed to be unique
152 assert( GetNetItem( aNewElement->GetNetname() ) == nullptr );
153 assert( GetNetItem( aNewElement->GetNetCode() ) == nullptr );
154
155 // add an entry for fast look up by a net name using a map
156 m_netNames.insert( std::make_pair( aNewElement->GetNetname(), aNewElement ) );
157 m_netCodes.insert( std::make_pair( aNewElement->GetNetCode(), aNewElement ) );
158 }
159
160
buildListOfNets()161 void NETINFO_LIST::buildListOfNets()
162 {
163 // Restore the initial state of NETINFO_ITEMs
164 for( NETINFO_ITEM* net : *this )
165 net->Clear();
166
167 m_parent->SynchronizeNetsAndNetClasses( );
168 m_parent->SetAreasNetCodesFromNetNames();
169 }
170
171
172 #if defined(DEBUG)
Show() const173 void NETINFO_LIST::Show() const
174 {
175 int i = 0;
176 NETNAMES_MAP::const_iterator it, itEnd;
177
178 for( it = m_netNames.begin(), itEnd = m_netNames.end(); it != itEnd; ++it )
179 {
180 wxLogDebug( "[%d]: netcode:%d netname:<%s>\n",
181 i++,
182 it->second->GetNetCode(),
183 TO_UTF8( it->second->GetNetname() ) );
184 }
185 }
186 #endif
187
188
getFreeNetCode()189 int NETINFO_LIST::getFreeNetCode()
190 {
191 do
192 {
193 if( m_newNetCode < 0 )
194 m_newNetCode = 0;
195 } while( m_netCodes.count( ++m_newNetCode ) != 0 );
196
197 return m_newNetCode;
198 }
199
200
Translate(int aNetCode) const201 int NETINFO_MAPPING::Translate( int aNetCode ) const
202 {
203 std::map<int, int>::const_iterator value = m_netMapping.find( aNetCode );
204
205 if( value != m_netMapping.end() )
206 return value->second;
207
208 // There was no entry for the given net code
209 return aNetCode;
210 }
211
212
Update()213 void NETINFO_MAPPING::Update()
214 {
215 // Collect all the used nets
216 std::set<int> nets;
217
218 // Be sure that the unconnected gets 0 and is mapped as 0
219 nets.insert( 0 );
220
221 // Zones
222 for( ZONE* zone : m_board->Zones() )
223 nets.insert( zone->GetNetCode() );
224
225 // Tracks
226 for( PCB_TRACK* track : m_board->Tracks() )
227 nets.insert( track->GetNetCode() );
228
229 // footprints/pads
230 for( FOOTPRINT* footprint : m_board->Footprints() )
231 {
232 for( PAD* pad : footprint->Pads() )
233 nets.insert( pad->GetNetCode() );
234 }
235
236 // Prepare the new mapping
237 m_netMapping.clear();
238
239 // Now the nets variable stores all the used net codes (not only for pads) and we are ready to
240 // assign new consecutive net numbers
241 int newNetCode = 0;
242
243 for( auto net : nets )
244 m_netMapping[net] = newNetCode++;
245 }
246
247
operator *() const248 NETINFO_ITEM* NETINFO_MAPPING::iterator::operator*() const
249 {
250 return m_mapping->m_board->FindNet( m_iterator->first );
251 }
252
253
operator ->() const254 NETINFO_ITEM* NETINFO_MAPPING::iterator::operator->() const
255 {
256 return m_mapping->m_board->FindNet( m_iterator->first );
257 }
258
259
260 const int NETINFO_LIST::UNCONNECTED = 0;
261 const int NETINFO_LIST::ORPHANED = -1;
262
263