KiCad PCB EDA Suite
erc_settings.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 CERN
5  * @author Jon Evans <jon@craftyjon.com>
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <erc_item.h>
22 #include <erc_settings.h>
23 #include <schematic.h>
24 #include <sch_marker.h>
25 #include <sch_screen.h>
27 #include <settings/parameters.h>
28 
29 
31 
32 
33 
34 #define OK PIN_ERROR::OK
35 #define ERR PIN_ERROR::PP_ERROR
36 #define WAR PIN_ERROR::WARNING
37 
42 {
43 /* I, O, Bi, 3S, Pas, NIC, UnS, PwrI, PwrO, OC, OE, NC */
44 /* I */ { OK, OK, OK, OK, OK, OK, WAR, OK, OK, OK, OK, ERR },
45 /* O */ { OK, ERR, OK, WAR, OK, OK, WAR, OK, ERR, ERR, ERR, ERR },
46 /* Bi */ { OK, OK, OK, OK, OK, OK, WAR, OK, WAR, OK, WAR, ERR },
47 /* 3S */ { OK, WAR, OK, OK, OK, OK, WAR, WAR, ERR, WAR, WAR, ERR },
48 /*Pas */ { OK, OK, OK, OK, OK, OK, WAR, OK, OK, OK, OK, ERR },
49 /*NIC */ { OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, ERR },
50 /*UnS */ { WAR, WAR, WAR, WAR, WAR, OK, WAR, WAR, WAR, WAR, WAR, ERR },
51 /*PwrI*/ { OK, OK, OK, WAR, OK, OK, WAR, OK, OK, OK, OK, ERR },
52 /*PwrO*/ { OK, ERR, WAR, ERR, OK, OK, WAR, OK, ERR, ERR, ERR, ERR },
53 /* OC */ { OK, ERR, OK, WAR, OK, OK, WAR, OK, ERR, OK, OK, ERR },
54 /* OE */ { OK, ERR, WAR, WAR, OK, OK, WAR, OK, ERR, OK, OK, ERR },
55 /* NC */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }
56 };
57 
58 
70 {
71 /* I, O, Bi, 3S, Pas, NIC, UnS, PwrI, PwrO, OC, OE, NC */
72 /* I */ { NOD, DRV, DRV, DRV, DRV, NOD, DRV, NOD, DRV, DRV, DRV, NPI },
73 /* O */ { DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, DRV, DRV, NPI },
74 /* Bi */ { DRV, DRV, DRV, DRV, DRV, NOD, DRV, NOD, DRV, DRV, DRV, NPI },
75 /* 3S */ { DRV, DRV, DRV, DRV, DRV, NOD, DRV, NOD, DRV, DRV, DRV, NPI },
76 /*Pas */ { DRV, DRV, DRV, DRV, DRV, NOD, DRV, NOD, DRV, DRV, DRV, NPI },
77 /*NIC */ { NOD, NOD, NOD, NOD, NOD, NOD, NOD, NOD, NOD, NOD, NOD, NPI },
78 /*UnS */ { DRV, DRV, DRV, DRV, DRV, NOD, DRV, NOD, DRV, DRV, DRV, NPI },
79 /*PwrI*/ { NOD, DRV, NOD, NOD, NOD, NOD, NOD, NOD, DRV, NOD, NOD, NPI },
80 /*PwrO*/ { DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, DRV, DRV, NPI },
81 /* OC */ { DRV, DRV, DRV, DRV, DRV, NOD, DRV, NOD, DRV, DRV, DRV, NPI },
82 /* OE */ { DRV, DRV, DRV, DRV, DRV, NOD, DRV, NOD, DRV, DRV, DRV, NPI },
83 /* NC */ { NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI }
84 };
85 
86 
87 ERC_SETTINGS::ERC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
88  NESTED_SETTINGS( "erc", ercSettingsSchemaVersion, aParent, aPath )
89 {
90  ResetPinMap();
91 
92  for( int i = ERCE_FIRST; i <= ERCE_LAST; ++i )
94 
95  // Error is the default setting so set non-error priorities here.
105 
106  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
107  [&]() -> nlohmann::json
108  {
109  nlohmann::json ret = {};
110 
111  for( const RC_ITEM& item : ERC_ITEM::GetItemsWithSeverities() )
112  {
113  wxString name = item.GetSettingsKey();
114  int code = item.GetErrorCode();
115 
116  if( name.IsEmpty() || m_Severities.count( code ) == 0 )
117  continue;
118 
119  ret[std::string( name.ToUTF8() )] = SeverityToString( m_Severities[code] );
120  }
121 
122  return ret;
123  },
124  [&]( const nlohmann::json& aJson )
125  {
126  if( !aJson.is_object() )
127  return;
128 
129  for( const RC_ITEM& item : ERC_ITEM::GetItemsWithSeverities() )
130  {
131  int code = item.GetErrorCode();
132  wxString name = item.GetSettingsKey();
133 
134  std::string key( name.ToUTF8() );
135 
136  if( aJson.contains( key ) )
137  m_Severities[code] = SeverityFromString( aJson[key] );
138  }
139  },
140  {} ) );
141 
142  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "erc_exclusions",
143  [&]() -> nlohmann::json
144  {
145  nlohmann::json js = nlohmann::json::array();
146 
147  for( const auto& entry : m_ErcExclusions )
148  js.push_back( entry );
149 
150  return js;
151  },
152  [&]( const nlohmann::json& aObj )
153  {
154  m_ErcExclusions.clear();
155 
156  if( !aObj.is_array() )
157  return;
158 
159  for( const nlohmann::json& entry : aObj )
160  {
161  if( entry.empty() )
162  continue;
163 
164  m_ErcExclusions.insert( entry.get<wxString>() );
165  }
166  },
167  {} ) );
168 
169  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "pin_map",
170  [&]() -> nlohmann::json
171  {
172  nlohmann::json ret = nlohmann::json::array();
173 
174  for( int i = 0; i < ELECTRICAL_PINTYPES_TOTAL; i++ )
175  {
176  nlohmann::json inner = nlohmann::json::array();
177 
178  for( int j = 0; j < ELECTRICAL_PINTYPES_TOTAL; j++ )
179  inner.push_back( static_cast<int>( GetPinMapValue( i, j ) ) );
180 
181  ret.push_back( inner );
182  }
183 
184  return ret;
185  },
186  [&]( const nlohmann::json& aJson )
187  {
188  if( !aJson.is_array() || aJson.size() != ELECTRICAL_PINTYPES_TOTAL )
189  return;
190 
191  for( size_t i = 0; i < ELECTRICAL_PINTYPES_TOTAL; i++ )
192  {
193  if( i > aJson.size() - 1 )
194  break;
195 
196  nlohmann::json inner = aJson[i];
197 
198  if( !inner.is_array() || inner.size() != ELECTRICAL_PINTYPES_TOTAL )
199  return;
200 
201  for( size_t j = 0; j < ELECTRICAL_PINTYPES_TOTAL; j++ )
202  {
203  if( inner[j].is_number_integer() )
204  {
205  int val = inner[j].get<int>();
206 
207  if( val >= 0 && val <= static_cast<int>( PIN_ERROR::UNCONNECTED ) )
208  SetPinMapValue( i, j, static_cast<PIN_ERROR>( val ) );
209  }
210  }
211  }
212  },
213  {} ) );
214 }
215 
216 
218 {
219  if( m_parent )
220  {
222  m_parent = nullptr;
223  }
224 }
225 
226 
227 SEVERITY ERC_SETTINGS::GetSeverity( int aErrorCode ) const
228 {
229  // Special-case pin-to-pin errors:
230  // Ignore-or-not is controlled by ERCE_PIN_TO_PIN_WARNING (for both)
231  // Warning-or-error is controlled by which errorCode it is
232  if( aErrorCode == ERCE_PIN_TO_PIN_ERROR )
233  {
234  wxASSERT( m_Severities.count( ERCE_PIN_TO_PIN_WARNING ) );
235 
237  return RPT_SEVERITY_IGNORE;
238  else
239  return RPT_SEVERITY_ERROR;
240  }
241  else if( aErrorCode == ERCE_PIN_TO_PIN_WARNING )
242  {
243  wxASSERT( m_Severities.count( ERCE_PIN_TO_PIN_WARNING ) );
244 
246  return RPT_SEVERITY_IGNORE;
247  else
248  return RPT_SEVERITY_WARNING;
249  }
250 
251  wxCHECK_MSG( m_Severities.count( aErrorCode ), RPT_SEVERITY_IGNORE,
252  "Missing severity from map in ERC_SETTINGS!" );
253 
254  return m_Severities.at( aErrorCode );
255 }
256 
257 
258 void ERC_SETTINGS::SetSeverity( int aErrorCode, SEVERITY aSeverity )
259 {
260  m_Severities[ aErrorCode ] = aSeverity;
261 }
262 
263 
265 {
266  memcpy( m_PinMap, m_defaultPinMap, sizeof( m_PinMap ) );
267 }
268 
269 
270 void SHEETLIST_ERC_ITEMS_PROVIDER::visitMarkers( std::function<void( SCH_MARKER* )> aVisitor ) const
271 {
272  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
273 
274  std::set<SCH_SCREEN*> seenScreens;
275 
276  for( unsigned i = 0; i < sheetList.size(); i++ )
277  {
278  bool firstTime = seenScreens.count( sheetList[i].LastScreen() ) == 0;
279 
280  if( firstTime )
281  seenScreens.insert( sheetList[i].LastScreen() );
282 
283  for( SCH_ITEM* item : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
284  {
285  SCH_MARKER* marker = static_cast<SCH_MARKER*>( item );
286 
287  if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
288  continue;
289 
290  // Don't show non-specific markers more than once
291  if( !firstTime &&
292  !static_cast<const ERC_ITEM*>( marker->GetRCItem().get() )->IsSheetSpecific() )
293  {
294  continue;
295  }
296 
297  aVisitor( marker );
298  }
299  }
300 }
301 
302 
304 {
305  m_severities = aSeverities;
306 
307  m_filteredMarkers.clear();
308 
309  ERC_SETTINGS& settings = m_schematic->ErcSettings();
310 
311  visitMarkers(
312  [&]( SCH_MARKER* aMarker )
313  {
314  SEVERITY markerSeverity;
315 
316  if( aMarker->IsExcluded() )
317  markerSeverity = RPT_SEVERITY_EXCLUSION;
318  else
319  markerSeverity = settings.GetSeverity( aMarker->GetRCItem()->GetErrorCode() );
320 
321  if( markerSeverity & m_severities )
322  m_filteredMarkers.push_back( aMarker );
323  } );
324 }
325 
326 
327 int SHEETLIST_ERC_ITEMS_PROVIDER::GetCount( int aSeverity ) const
328 {
329  if( aSeverity < 0 )
330  return m_filteredMarkers.size();
331 
332  int count = 0;
333 
334  const ERC_SETTINGS& settings = m_schematic->ErcSettings();
335 
336  visitMarkers(
337  [&]( SCH_MARKER* aMarker )
338  {
339  SEVERITY markerSeverity;
340 
341  if( aMarker->IsExcluded() )
342  markerSeverity = RPT_SEVERITY_EXCLUSION;
343  else
344  markerSeverity = settings.GetSeverity( aMarker->GetRCItem()->GetErrorCode() );
345 
346  if( markerSeverity == aSeverity )
347  count++;
348  } );
349 
350  return count;
351 }
352 
353 
354 std::shared_ptr<ERC_ITEM> SHEETLIST_ERC_ITEMS_PROVIDER::GetERCItem( int aIndex ) const
355 {
356  SCH_MARKER* marker = m_filteredMarkers[ aIndex ];
357 
358  return marker ? std::static_pointer_cast<ERC_ITEM>( marker->GetRCItem() ) : nullptr;
359 }
360 
361 
362 std::shared_ptr<RC_ITEM> SHEETLIST_ERC_ITEMS_PROVIDER::GetItem( int aIndex ) const
363 {
364  return GetERCItem( aIndex );
365 }
366 
367 
368 void SHEETLIST_ERC_ITEMS_PROVIDER::DeleteItem( int aIndex, bool aDeep )
369 {
370  SCH_MARKER* marker = m_filteredMarkers[ aIndex ];
371  m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex );
372 
373  if( aDeep )
374  {
375  SCH_SCREENS screens( m_schematic->Root() );
376  screens.DeleteMarker( marker );
377  }
378 }
379 
380 
381 void SHEETLIST_ERC_ITEMS_PROVIDER::DeleteAllItems( bool aIncludeExclusions, bool aDeep )
382 {
383  // Filtered list was already handled through DeleteItem() by the tree control
384 
385  if( aDeep )
386  {
387  SCH_SCREENS screens( m_schematic->Root() );
388  screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC, aIncludeExclusions );
389  }
390 }
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
static int m_PinMinDrive[ELECTRICAL_PINTYPES_TOTAL][ELECTRICAL_PINTYPES_TOTAL]
Look up table which gives the minimal drive for a pair of connected pins on a net.
Definition: erc_settings.h:171
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
#define NOD
Definition: erc_settings.h:97
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: erc_item.h:50
#define WAR
A holder for a rule check item, DRC in Pcbnew or ERC in Eeschema.
Definition: rc_item.h:74
#define OK
PIN_ERROR
The values a pin-to-pin entry in the pin matrix can take on.
Definition: erc_settings.h:85
void SetSeverity(int aErrorCode, SEVERITY aSeverity)
nlohmann::json json
Definition: gerbview.cpp:41
Library symbol changed from current symbol in schematic or the library symbol link no longer valid.
Definition: erc_settings.h:66
std::set< wxString > m_ErcExclusions
Definition: erc_settings.h:167
#define ERR
void ResetPinMap()
static PIN_ERROR m_defaultPinMap[ELECTRICAL_PINTYPES_TOTAL][ELECTRICAL_PINTYPES_TOTAL]
Default Look up table which gives the ERC error level for a pair of connected pins.
Definition: erc_settings.h:175
void visitMarkers(std::function< void(SCH_MARKER *)> aVisitor) const
void DeleteItem(int aIndex, bool aDeep) override
Remove (and optionally deletes) the indexed item from the list.
NESTED_SETTINGS is a JSON_SETTINGS that lives inside a JSON_SETTINGS.
const int ercSettingsSchemaVersion
std::vector< SCH_MARKER * > m_filteredMarkers
Definition: erc_settings.h:188
std::shared_ptr< ERC_ITEM > GetERCItem(int aIndex) const
void DeleteAllMarkers(enum MARKER_BASE::TYPEMARKER aMarkerType, bool aIncludeExclusions)
Delete all electronic rules check markers of aMarkerType from all the screens in the list.
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
2 labels are equal for case insensitive comparisons.
Definition: erc_settings.h:50
PIN_ERROR m_PinMap[ELECTRICAL_PINTYPES_TOTAL][ELECTRICAL_PINTYPES_TOTAL]
Definition: erc_settings.h:169
bool IsExcluded() const
Definition: marker_base.h:94
Container for ERC settings.
Definition: erc_settings.h:106
int GetCount(int aSeverity=-1) const override
SEVERITY
A wire connected to a bus doesn't match the bus.
Definition: erc_settings.h:57
void DeleteMarker(SCH_MARKER *aMarker)
Delete a specific marker.
A no connect symbol is not connected to anything.
Definition: erc_settings.h:48
#define NPI
Types of drive on a net (used for legacy ERC)
Definition: erc_settings.h:94
A global label is unique.
Definition: erc_settings.h:63
std::map< int, SEVERITY > m_Severities
Definition: erc_settings.h:166
A no connect symbol is connected to more than 1 pin.
Definition: erc_settings.h:47
SCH_SHEET_LIST GetSheets() const override
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:87
ERC_SETTINGS(JSON_SETTINGS *aParent, const std::string &aPath)
SCH_SHEET & Root() const
Definition: schematic.h:92
wxString SeverityToString(const SEVERITY &aSeverity)
Definition: ui_common.cpp:56
const char * name
Definition: DXF_plotter.cpp:56
enum TYPEMARKER GetMarkerType() const
Definition: marker_base.h:92
SEVERITY SeverityFromString(const wxString &aSeverity)
Definition: ui_common.cpp:45
void SetPinMapValue(int aFirstType, int aSecondType, PIN_ERROR aValue)
Definition: erc_settings.h:146
PIN_ERROR GetPinMapValue(int aFirstType, int aSecondType) const
Definition: erc_settings.h:134
void DeleteAllItems(bool aIncludeExclusions, bool aDeep) override
virtual ~ERC_SETTINGS()
std::shared_ptr< RC_ITEM > GetItem(int aIndex) const override
Retrieve a RC_ITEM by index.
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:174
#define ELECTRICAL_PINTYPES_TOTAL
Definition: pin_type.h:53
void ReleaseNestedSettings(NESTED_SETTINGS *aSettings)
Saves and frees a nested settings object, if it exists within this one.
Conflicting drivers (labels, etc) on a subgraph.
Definition: erc_settings.h:56
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:193
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:100
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:557
void SetSeverities(int aSeverities) override
SEVERITY GetSeverity(int aErrorCode) const
#define DRV
Definition: erc_settings.h:95