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>
26 #include <settings/parameters.h>
27 
28 
30 
31 
32 
33 #define OK PIN_ERROR::OK
34 #define ERR PIN_ERROR::PP_ERROR
35 #define WAR PIN_ERROR::WARNING
36 
41  {
42 /* I, O, Bi, 3S, Pas, UnS, PwrI, PwrO, OC, OE, NC */
43 /* I */ { OK, OK, OK, OK, OK, WAR, OK, OK, OK, OK, ERR },
44 /* O */ { OK, ERR, OK, WAR, OK, WAR, OK, ERR, ERR, ERR, ERR },
45 /* Bi*/ { OK, OK, OK, OK, OK, WAR, OK, WAR, OK, WAR, ERR },
46 /* 3S*/ { OK, WAR, OK, OK, OK, WAR, WAR, ERR, WAR, WAR, ERR },
47 /*Pas*/ { OK, OK, OK, OK, OK, WAR, OK, OK, OK, OK, ERR },
48 /*UnS */ { WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, WAR, ERR },
49 /*PwrI*/ { OK, OK, OK, WAR, OK, WAR, OK, OK, OK, OK, ERR },
50 /*PwrO*/ { OK, ERR, WAR, ERR, OK, WAR, OK, ERR, ERR, ERR, ERR },
51 /* OC */ { OK, ERR, OK, WAR, OK, WAR, OK, ERR, OK, OK, ERR },
52 /* OE */ { OK, ERR, WAR, WAR, OK, WAR, OK, ERR, OK, OK, ERR },
53 /* NC */ { ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR }
54  };
55 
56 
68  {
69 /* In Out, Bi, 3S, Pas, UnS, PwrI,PwrO,OC, OE, NC */
70 /* In*/ { NOD, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NPI },
71 /*Out*/ { DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, NPI },
72 /* Bi*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NPI },
73 /* 3S*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NPI },
74 /*Pas*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NPI },
75 /*UnS*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NPI },
76 /*PwrI*/ { NOD, DRV, NOD, NOD, NOD, NOD, NOD, DRV, NOD, NOD, NPI },
77 /*PwrO*/ { DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, DRV, NPI },
78 /* OC*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NPI },
79 /* OE*/ { DRV, DRV, DRV, DRV, DRV, DRV, NOD, DRV, DRV, DRV, NPI },
80 /* NC*/ { NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI, NPI }
81  };
82 
83 
84 ERC_SETTINGS::ERC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
85  NESTED_SETTINGS( "erc", ercSettingsSchemaVersion, aParent, aPath )
86 {
87  ResetPinMap();
88 
89  for( int i = ERCE_FIRST; i <= ERCE_LAST; ++i )
91 
94 
95  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "rule_severities",
96  [&]() -> nlohmann::json
97  {
98  nlohmann::json ret = {};
99 
100  for( const RC_ITEM& item : ERC_ITEM::GetItemsWithSeverities() )
101  {
102  int code = item.GetErrorCode();
103 
104  if( !m_Severities.count( code ) )
105  continue;
106 
107  wxString name = item.GetSettingsKey();
108 
109  ret[std::string( name.ToUTF8() )] =
110  SeverityToString( static_cast<SEVERITY>( m_Severities[code] ) );
111  }
112 
113  return ret;
114  },
115  [&]( const nlohmann::json& aJson )
116  {
117  if( !aJson.is_object() )
118  return;
119 
120  for( const RC_ITEM& item : ERC_ITEM::GetItemsWithSeverities() )
121  {
122  int code = item.GetErrorCode();
123  wxString name = item.GetSettingsKey();
124 
125  std::string key( name.ToUTF8() );
126 
127  if( aJson.contains( key ) )
128  m_Severities[code] = SeverityFromString( aJson[key] );
129  }
130  },
131  {} ) );
132 
133  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "pin_map",
134  [&]() -> nlohmann::json
135  {
136  nlohmann::json ret = nlohmann::json::array();
137 
138  for( int i = 0; i < ELECTRICAL_PINTYPES_TOTAL; i++ )
139  {
140  nlohmann::json inner = nlohmann::json::array();
141 
142  for( int j = 0; j < ELECTRICAL_PINTYPES_TOTAL; j++ )
143  inner.push_back( static_cast<int>( GetPinMapValue( i, j ) ) );
144 
145  ret.push_back( inner );
146  }
147 
148  return ret;
149  },
150  [&]( const nlohmann::json& aJson )
151  {
152  if( !aJson.is_array() || aJson.size() != ELECTRICAL_PINTYPES_TOTAL )
153  return;
154 
155  for( size_t i = 0; i < ELECTRICAL_PINTYPES_TOTAL; i++ )
156  {
157  if( i > aJson.size() - 1 )
158  break;
159 
160  nlohmann::json inner = aJson[i];
161 
162  if( !inner.is_array() || inner.size() != ELECTRICAL_PINTYPES_TOTAL )
163  return;
164 
165  for( size_t j = 0; j < ELECTRICAL_PINTYPES_TOTAL; j++ )
166  {
167  if( inner[j].is_number_integer() )
168  {
169  int val = inner[j].get<int>();
170 
171  if( val >= 0 && val <= static_cast<int>( PIN_ERROR::UNCONNECTED ) )
172  SetPinMapValue( i, j, static_cast<PIN_ERROR>( val ) );
173  }
174  }
175  }
176  },
177  {} ) );
178 }
179 
180 
182 {
183  if( m_parent )
184  {
186  m_parent = nullptr;
187  }
188 }
189 
190 
191 int ERC_SETTINGS::GetSeverity( int aErrorCode ) const
192 {
193  // Special-case pin-to-pin errors:
194  // Ignore-or-not is controlled by ERCE_PIN_TO_PIN_WARNING (for both)
195  // Warning-or-error is controlled by which errorCode it is
196  if( aErrorCode == ERCE_PIN_TO_PIN_ERROR )
197  {
198  wxASSERT( m_Severities.count( ERCE_PIN_TO_PIN_WARNING ) );
199 
201  return RPT_SEVERITY_IGNORE;
202  else
203  return RPT_SEVERITY_ERROR;
204  }
205  else if( aErrorCode == ERCE_PIN_TO_PIN_WARNING )
206  {
207  wxASSERT( m_Severities.count( ERCE_PIN_TO_PIN_WARNING ) );
208 
210  return RPT_SEVERITY_IGNORE;
211  else
212  return RPT_SEVERITY_WARNING;
213  }
214 
215  wxCHECK_MSG( m_Severities.count( aErrorCode ), RPT_SEVERITY_IGNORE,
216  "Missing severity from map in ERC_SETTINGS!" );
217 
218  return m_Severities.at( aErrorCode );
219 }
220 
221 
222 void ERC_SETTINGS::SetSeverity( int aErrorCode, int aSeverity )
223 {
224  m_Severities[ aErrorCode ] = aSeverity;
225 }
226 
227 
229 {
230  memcpy( m_PinMap, m_defaultPinMap, sizeof( m_PinMap ) );
231 }
232 
233 
235 {
236  m_severities = aSeverities;
237 
238  m_filteredMarkers.clear();
239 
240  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
241  ERC_SETTINGS& settings = m_schematic->ErcSettings();
242 
243  for( unsigned i = 0; i < sheetList.size(); i++ )
244  {
245  for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
246  {
247  SCH_MARKER* marker = static_cast<SCH_MARKER*>( aItem );
248  int markerSeverity;
249 
250  if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
251  continue;
252 
253  if( marker->IsExcluded() )
254  markerSeverity = RPT_SEVERITY_EXCLUSION;
255  else
256  markerSeverity = settings.GetSeverity( marker->GetRCItem()->GetErrorCode() );
257 
258  if( markerSeverity & m_severities )
259  m_filteredMarkers.push_back( marker );
260  }
261  }
262 }
263 
264 
266 {
267  if( aSeverity < 0 )
268  return m_filteredMarkers.size();
269 
270  int count = 0;
271 
272  SCH_SHEET_LIST sheetList = m_schematic->GetSheets();
273  ERC_SETTINGS& settings = m_schematic->ErcSettings();
274 
275  for( unsigned i = 0; i < sheetList.size(); i++ )
276  {
277  for( SCH_ITEM* aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
278  {
279  SCH_MARKER* marker = static_cast<SCH_MARKER*>( aItem );
280  int markerSeverity;
281 
282  if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
283  continue;
284 
285  if( marker->IsExcluded() )
286  markerSeverity = RPT_SEVERITY_EXCLUSION;
287  else
288  markerSeverity = settings.GetSeverity( marker->GetRCItem()->GetErrorCode() );
289 
290  if( markerSeverity == aSeverity )
291  count++;
292  }
293  }
294 
295  return count;
296 }
297 
298 
300 {
301  SCH_MARKER* marker = m_filteredMarkers[ aIndex ];
302 
303  return marker ? static_cast<ERC_ITEM*>( marker->GetRCItem() ) : nullptr;
304 }
305 
306 
307 void SHEETLIST_ERC_ITEMS_PROVIDER::DeleteItem( int aIndex, bool aDeep )
308 {
309  SCH_MARKER* marker = m_filteredMarkers[ aIndex ];
310  m_filteredMarkers.erase( m_filteredMarkers.begin() + aIndex );
311 
312  if( aDeep )
313  {
314  SCH_SCREENS screens( m_schematic->Root() );
315  screens.DeleteMarker( marker );
316  }
317 }
318 
319 
320 void SHEETLIST_ERC_ITEMS_PROVIDER::DeleteAllItems( bool aIncludeExclusions, bool aDeep )
321 {
322  // Filtered list was already handled through DeleteItem() by the tree control
323 
324  if( aDeep )
325  {
326  SCH_SCREENS screens( m_schematic->Root() );
327  screens.DeleteAllMarkers( MARKER_BASE::MARKER_ERC, aIncludeExclusions );
328  }
329 }
SCH_SHEET_LIST.
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:161
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
SCH_SHEET_LIST GetSheets() const
Builds and returns an updated schematic hierarchy TODO: can this be cached?
Definition: schematic.h:92
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:296
RC_ITEM * GetRCItem()
Function GetReporter returns the DRC_ITEM held within this MARKER so that its interface may be used.
Definition: marker_base.h:117
#define NOD
Definition: erc_settings.h:78
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: erc_item.h:39
#define WAR
RC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
Definition: rc_item.h:73
#define OK
PIN_ERROR
The values a pin-to-pin entry in the pin matrix can take on.
Definition: erc_settings.h:66
nlohmann::json json
Definition: gerbview.cpp:40
#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:165
void DeleteItem(int aIndex, bool aDeep) override
Function DeleteItem removes (and optionally deletes) the indexed item from the list.
NESTED_SETTINGS is a JSON_SETTINGS that lives inside a JSON_SETTINGS.
const int ercSettingsSchemaVersion
void SetSeverity(int aErrorCode, int aSeverity)
std::vector< SCH_MARKER * > m_filteredMarkers
Definition: erc_settings.h:178
int GetSeverity(int aErrorCode) const
ERC_ITEM * GetItem(int aIndex) override
Function GetItem retrieves a RC_ITEM by index.
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.
int GetErrorCode() const
Definition: rc_item.h:156
int GetCount(int aSeverity=-1) override
PIN_ERROR m_PinMap[ELECTRICAL_PINTYPES_TOTAL][ELECTRICAL_PINTYPES_TOTAL]
Definition: erc_settings.h:159
bool IsExcluded() const
Definition: marker_base.h:108
std::map< int, int > m_Severities
Definition: erc_settings.h:157
Container for ERC settings.
Definition: erc_settings.h:87
void DeleteMarker(SCH_MARKER *aMarker)
Delete a specific marker.
#define NPI
Types of drive on a net (used for legacy ERC)
Definition: erc_settings.h:75
ERC_SETTINGS(JSON_SETTINGS *aParent, const std::string &aPath)
SCH_SHEET & Root() const
Definition: schematic.h:97
wxString SeverityToString(const SEVERITY &aSeverity)
Definition: ui_common.cpp:119
const char * name
Definition: DXF_plotter.cpp:60
enum TYPEMARKER GetMarkerType() const
Definition: marker_base.h:106
SEVERITY SeverityFromString(const wxString &aSeverity)
Definition: ui_common.cpp:108
void SetPinMapValue(int aFirstType, int aSecondType, PIN_ERROR aValue)
Definition: erc_settings.h:137
PIN_ERROR GetPinMapValue(int aFirstType, int aSecondType) const
Definition: erc_settings.h:125
void DeleteAllItems(bool aIncludeExclusions, bool aDeep) override
virtual ~ERC_SETTINGS()
ERC_SETTINGS & ErcSettings() const
Definition: schematic.cpp:145
#define ELECTRICAL_PINTYPES_TOTAL
Definition: pin_type.h:54
void ReleaseNestedSettings(NESTED_SETTINGS *aSettings)
Saves and frees a nested settings object, if it exists within this one.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:187
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:528
void SetSeverities(int aSeverities) override
#define DRV
Definition: erc_settings.h:76