KiCad PCB EDA Suite
drc_engine.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-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com
6  * Copyright (C) 2017-2020 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <reporter.h>
28 #include <kicad_string.h>
29 #include <drc/drc_engine.h>
30 #include <drc/drc_rule_parser.h>
31 #include <drc/drc_rule.h>
32 #include <drc/drc_rule_condition.h>
33 #include <drc/drc_test_provider.h>
34 #include <track.h>
35 
36 void drcPrintDebugMessage( int level, const wxString& msg, const char *function, int line )
37 {
38  wxString valueStr;
39 
40  if( wxGetEnv( "DRC_DEBUG", &valueStr ) )
41  {
42  int setLevel = wxAtoi( valueStr );
43 
44  if( level <= setLevel )
45  {
46  printf("%-30s:%d | %s\n", function, line, (const char *) msg.c_str() );
47  }
48  }
49 }
50 
51 
53  m_designSettings ( aSettings ),
54  m_board( aBoard ),
55  m_worksheet( nullptr ),
56  m_schematicNetlist( nullptr ),
57  m_rulesValid( false ),
58  m_userUnits( EDA_UNITS::MILLIMETRES ),
59  m_reportAllTrackErrors( false ),
60  m_testFootprints( false ),
61  m_reporter( nullptr ),
62  m_progressReporter( nullptr )
63 {
64  m_errorLimits.resize( DRCE_LAST + 1 );
65 
66  for( int ii = DRCE_FIRST; ii <= DRCE_LAST; ++ii )
67  m_errorLimits[ ii ] = INT_MAX;
68 }
69 
70 
72 {
73  for( DRC_RULE* rule : m_rules )
74  delete rule;
75 
76  for( std::pair< DRC_CONSTRAINT_TYPE_T,
77  std::vector<CONSTRAINT_WITH_CONDITIONS*>* > pair : m_constraintMap )
78  {
79  for( CONSTRAINT_WITH_CONDITIONS* constraintWithCondition : *pair.second )
80  delete constraintWithCondition;
81 
82  delete pair.second;
83  }
84 }
85 
86 
87 static bool isKeepoutZone( const BOARD_ITEM* aItem, bool aCheckFlags )
88 {
89  if( !aItem )
90  return false;
91 
92  if( aItem->Type() != PCB_ZONE_T && aItem->Type() != PCB_FP_ZONE_T )
93  return false;
94 
95  const ZONE* zone = static_cast<const ZONE*>( aItem );
96 
97  if( !zone->GetIsRuleArea() )
98  return false;
99 
100  if( aCheckFlags )
101  {
102  if( !zone->GetDoNotAllowTracks()
103  && !zone->GetDoNotAllowVias()
104  && !zone->GetDoNotAllowPads()
105  && !zone->GetDoNotAllowCopperPour()
106  && !zone->GetDoNotAllowFootprints() )
107  {
108  return false;
109  }
110  }
111 
112  return true;
113 }
114 
115 
117 {
118  DRC_RULE *rule = new DRC_RULE;
119 
120  rule->m_Name = name;
121  rule->m_Implicit = true;
122 
123  addRule( rule );
124 
125  return rule;
126 }
127 
128 
130 {
131  ReportAux( wxString::Format( "Building implicit rules (per-item/class overrides, etc...)" ) );
132 
134 
135  // 1) global defaults
136 
137  DRC_RULE* rule = createImplicitRule( _( "board setup constraints" ) );
138 
139  DRC_CONSTRAINT clearanceConstraint( CLEARANCE_CONSTRAINT );
140  clearanceConstraint.Value().SetMin( bds.m_MinClearance );
141  rule->AddConstraint( clearanceConstraint );
142 
143  DRC_CONSTRAINT widthConstraint( TRACK_WIDTH_CONSTRAINT );
144  widthConstraint.Value().SetMin( bds.m_TrackMinWidth );
145  rule->AddConstraint( widthConstraint );
146 
147  DRC_CONSTRAINT drillConstraint( HOLE_SIZE_CONSTRAINT );
148  drillConstraint.Value().SetMin( bds.m_MinThroughDrill );
149  rule->AddConstraint( drillConstraint );
150 
151  DRC_CONSTRAINT annulusConstraint( ANNULAR_WIDTH_CONSTRAINT );
152  annulusConstraint.Value().SetMin( bds.m_ViasMinAnnulus );
153  rule->AddConstraint( annulusConstraint );
154 
155  DRC_CONSTRAINT diameterConstraint( VIA_DIAMETER_CONSTRAINT );
156  diameterConstraint.Value().SetMin( bds.m_ViasMinSize );
157  rule->AddConstraint( diameterConstraint );
158 
159  DRC_CONSTRAINT edgeClearanceConstraint( EDGE_CLEARANCE_CONSTRAINT );
160  edgeClearanceConstraint.Value().SetMin( bds.m_CopperEdgeClearance );
161  rule->AddConstraint( edgeClearanceConstraint );
162 
163  DRC_CONSTRAINT holeClearanceConstraint( HOLE_CLEARANCE_CONSTRAINT );
164  holeClearanceConstraint.Value().SetMin( bds.m_HoleClearance );
165  rule->AddConstraint( holeClearanceConstraint );
166 
167  DRC_CONSTRAINT holeToHoleConstraint( HOLE_TO_HOLE_CONSTRAINT );
168  holeToHoleConstraint.Value().SetMin( bds.m_HoleToHoleMin );
169  rule->AddConstraint( holeToHoleConstraint );
170 
171  DRC_CONSTRAINT courtyardClearanceConstraint( COURTYARD_CLEARANCE_CONSTRAINT );
172  holeToHoleConstraint.Value().SetMin( 0 );
173  rule->AddConstraint( courtyardClearanceConstraint );
174 
175  DRC_CONSTRAINT diffPairGapConstraint( DIFF_PAIR_GAP_CONSTRAINT );
176  diffPairGapConstraint.Value().SetMin( bds.GetDefault()->GetClearance() );
177  rule->AddConstraint( diffPairGapConstraint );
178 
179  rule = createImplicitRule( _( "board setup constraints" ) );
180  rule->m_LayerCondition = LSET( 2, F_SilkS, B_SilkS );
181  DRC_CONSTRAINT silkClearanceConstraint( SILK_CLEARANCE_CONSTRAINT );
182  silkClearanceConstraint.Value().SetMin( bds.m_SilkClearance );
183  rule->AddConstraint( silkClearanceConstraint );
184 
185 
186  // 2) micro-via specific defaults (new DRC doesn't treat microvias in any special way)
187 
188  DRC_RULE* uViaRule = createImplicitRule( _( "board setup micro-via constraints" ) );
189 
190  uViaRule->m_Condition = new DRC_RULE_CONDITION( "A.Via_Type == 'Micro'" );
191 
192  DRC_CONSTRAINT uViaDrillConstraint( HOLE_SIZE_CONSTRAINT );
193  uViaDrillConstraint.Value().SetMin( bds.m_MicroViasMinDrill );
194  uViaRule->AddConstraint( uViaDrillConstraint );
195 
196  DRC_CONSTRAINT uViaDiameterConstraint( VIA_DIAMETER_CONSTRAINT );
197  uViaDiameterConstraint.Value().SetMin( bds.m_MicroViasMinSize );
198  uViaRule->AddConstraint( uViaDiameterConstraint );
199 
200  if( !bds.m_MicroViasAllowed )
201  {
202  DRC_CONSTRAINT disallowConstraint( DISALLOW_CONSTRAINT );
203  disallowConstraint.m_DisallowFlags = DRC_DISALLOW_MICRO_VIAS;
204  uViaRule->AddConstraint( disallowConstraint );
205  }
206 
207  if( !bds.m_BlindBuriedViaAllowed )
208  {
209  DRC_RULE* bbViaRule = createImplicitRule( _( "board setup constraints" ) );
210 
211  bbViaRule->m_Condition = new DRC_RULE_CONDITION( "A.Via_Type == 'Blind/buried'" );
212 
213  DRC_CONSTRAINT disallowConstraint( DISALLOW_CONSTRAINT );
214  disallowConstraint.m_DisallowFlags = DRC_DISALLOW_BB_VIAS;
215  bbViaRule->AddConstraint( disallowConstraint );
216  }
217 
218  // 3) per-netclass rules
219 
220  std::vector<DRC_RULE*> netclassClearanceRules;
221  std::vector<DRC_RULE*> netclassItemSpecificRules;
222 
223  auto makeNetclassRules =
224  [&]( const NETCLASSPTR& nc, bool isDefault )
225  {
226  wxString ncName = nc->GetName();
227 
228  DRC_RULE* netclassRule;
229  wxString expr;
230 
231  if( nc->GetClearance() || nc->GetTrackWidth() )
232  {
233  netclassRule = new DRC_RULE;
234  netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
235  netclassRule->m_Implicit = true;
236 
237  expr = wxString::Format( "A.NetClass == '%s'",
238  ncName );
239  netclassRule->m_Condition = new DRC_RULE_CONDITION( expr );
240  netclassClearanceRules.push_back( netclassRule );
241 
242  if( nc->GetClearance() )
243  {
244  DRC_CONSTRAINT constraint( CLEARANCE_CONSTRAINT );
245  constraint.Value().SetMin( std::max( bds.m_MinClearance, nc->GetClearance() ) );
246  netclassRule->AddConstraint( constraint );
247  }
248 
249  if( nc->GetTrackWidth() )
250  {
252  constraint.Value().SetMin( bds.m_TrackMinWidth );
253  constraint.Value().SetOpt( nc->GetTrackWidth() );
254  netclassRule->AddConstraint( constraint );
255  }
256  }
257 
258  if( nc->GetDiffPairWidth() || nc->GetDiffPairGap() )
259  {
260  netclassRule = new DRC_RULE;
261  netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
262  netclassRule->m_Implicit = true;
263 
264  expr = wxString::Format( "A.NetClass == '%s' && A.isDiffPair()",
265  ncName );
266  netclassRule->m_Condition = new DRC_RULE_CONDITION( expr );
267  netclassItemSpecificRules.push_back( netclassRule );
268 
269  if( nc->GetDiffPairWidth() )
270  {
272  constraint.Value().SetMin( bds.m_TrackMinWidth );
273  constraint.Value().SetOpt( nc->GetDiffPairWidth() );
274  netclassRule->AddConstraint( constraint );
275  }
276 
277  if( nc->GetDiffPairGap() )
278  {
280  constraint.Value().SetMin( std::max( bds.m_MinClearance, nc->GetClearance() ) );
281  constraint.Value().SetOpt( nc->GetDiffPairGap() );
282  netclassRule->AddConstraint( constraint );
283  }
284  }
285 
286  if( nc->GetViaDiameter() || nc->GetViaDrill() )
287  {
288  netclassRule = new DRC_RULE;
289  netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
290  netclassRule->m_Implicit = true;
291 
292  expr = wxString::Format( "A.NetClass == '%s' && A.Via_Type != 'Micro'",
293  ncName );
294  netclassRule->m_Condition = new DRC_RULE_CONDITION( expr );
295  netclassItemSpecificRules.push_back( netclassRule );
296 
297  if( nc->GetViaDiameter() )
298  {
300  constraint.Value().SetMin( bds.m_ViasMinSize );
301  constraint.Value().SetOpt( nc->GetViaDiameter() );
302  netclassRule->AddConstraint( constraint );
303  }
304 
305  if( nc->GetViaDrill() )
306  {
307  DRC_CONSTRAINT constraint( HOLE_SIZE_CONSTRAINT );
308  constraint.Value().SetMin( bds.m_MinThroughDrill );
309  constraint.Value().SetOpt( nc->GetViaDrill() );
310  netclassRule->AddConstraint( constraint );
311  }
312  }
313 
314  if( nc->GetuViaDiameter() || nc->GetuViaDrill() )
315  {
316  netclassRule = new DRC_RULE;
317  netclassRule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
318  netclassRule->m_Implicit = true;
319 
320  expr = wxString::Format( "A.NetClass == '%s' && A.Via_Type == 'Micro'",
321  ncName );
322  netclassRule->m_Condition = new DRC_RULE_CONDITION( expr );
323  netclassItemSpecificRules.push_back( netclassRule );
324 
325  if( nc->GetuViaDiameter() )
326  {
328  constraint.Value().SetMin( bds.m_MicroViasMinSize );
329  constraint.Value().SetMin( nc->GetuViaDiameter() );
330  netclassRule->AddConstraint( constraint );
331  }
332 
333  if( nc->GetuViaDrill() )
334  {
335  DRC_CONSTRAINT constraint( HOLE_SIZE_CONSTRAINT );
336  constraint.Value().SetMin( bds.m_MicroViasMinDrill );
337  constraint.Value().SetOpt( nc->GetuViaDrill() );
338  netclassRule->AddConstraint( constraint );
339  }
340  }
341  };
342 
344  makeNetclassRules( bds.GetNetClasses().GetDefault(), true );
345 
346  for( const std::pair<const wxString, NETCLASSPTR>& netclass : bds.GetNetClasses() )
347  makeNetclassRules( netclass.second, false );
348 
349  // The netclass clearance rules have to be sorted by min clearance so the right one fires
350  // if 'A' and 'B' belong to two different netclasses.
351  //
352  // The item-specific netclass rules are all unary, so there's no 'A' vs 'B' issue.
353 
354  std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
355  []( DRC_RULE* lhs, DRC_RULE* rhs )
356  {
357  return lhs->m_Constraints[0].m_Value.Min()
358  < rhs->m_Constraints[0].m_Value.Min();
359  } );
360 
361  for( DRC_RULE* ncRule : netclassClearanceRules )
362  addRule( ncRule );
363 
364  for( DRC_RULE* ncRule : netclassItemSpecificRules )
365  addRule( ncRule );
366 
367  // 3) keepout area rules
368 
369  auto addKeepoutConstraint =
370  [&rule]( int aConstraint )
371  {
372  DRC_CONSTRAINT disallowConstraint( DISALLOW_CONSTRAINT );
373  disallowConstraint.m_DisallowFlags = aConstraint;
374  rule->AddConstraint( disallowConstraint );
375  };
376 
377  std::vector<ZONE*> keepoutZones;
378 
379  for( ZONE* zone : m_board->Zones() )
380  {
381  if( isKeepoutZone( zone, true ) )
382  keepoutZones.push_back( zone );
383  }
384 
385  for( FOOTPRINT* footprint : m_board->Footprints() )
386  {
387  for( ZONE* zone : footprint->Zones() )
388  {
389  if( isKeepoutZone( zone, true ) )
390  keepoutZones.push_back( zone );
391  }
392  }
393 
394  for( ZONE* zone : keepoutZones )
395  {
396  wxString name = zone->GetZoneName();
397 
398  if( name.IsEmpty() )
399  {
400  rule = createImplicitRule( _( "keepout area" ) );
401  name = zone->m_Uuid.AsString();
402  }
403  else
404  {
405  rule = createImplicitRule( wxString::Format( _( "keepout area '%s'" ), name ) );
406  }
407 
408  rule->m_Condition = new DRC_RULE_CONDITION( wxString::Format( "A.insideArea('%s')",
409  name ) );
410 
411  rule->m_LayerCondition = zone->GetLayerSet();
412 
413  if( zone->GetDoNotAllowTracks() )
414  addKeepoutConstraint( DRC_DISALLOW_TRACKS );
415 
416  if( zone->GetDoNotAllowVias() )
417  addKeepoutConstraint( DRC_DISALLOW_VIAS );
418 
419  if( zone->GetDoNotAllowPads() )
420  addKeepoutConstraint( DRC_DISALLOW_PADS );
421 
422  if( zone->GetDoNotAllowCopperPour() )
423  addKeepoutConstraint( DRC_DISALLOW_ZONES );
424 
425  if( zone->GetDoNotAllowFootprints() )
426  addKeepoutConstraint( DRC_DISALLOW_FOOTPRINTS );
427  }
428 
429  ReportAux( wxString::Format( "Building %d implicit netclass rules",
430  (int) netclassClearanceRules.size() ) );
431 }
432 
433 static wxString formatConstraint( const DRC_CONSTRAINT& constraint )
434 {
435  struct FORMATTER
436  {
438  wxString name;
439  std::function<wxString(const DRC_CONSTRAINT&)> formatter;
440  };
441 
442  auto formatMinMax =
443  []( const DRC_CONSTRAINT& c ) -> wxString
444  {
445  wxString str;
446  const auto value = c.GetValue();
447 
448  if ( value.HasMin() )
449  str += wxString::Format( " min: %d", value.Min() );
450 
451  if ( value.HasOpt() )
452  str += wxString::Format( " opt: %d", value.Opt() );
453 
454  if ( value.HasMax() )
455  str += wxString::Format( " max: %d", value.Max() );
456 
457  return str;
458  };
459 
460  std::vector<FORMATTER> formats =
461  {
462  { CLEARANCE_CONSTRAINT, "clearance", formatMinMax },
463  { HOLE_CLEARANCE_CONSTRAINT, "hole_clearance", formatMinMax },
464  { HOLE_TO_HOLE_CONSTRAINT, "hole_to_hole", formatMinMax },
465  { EDGE_CLEARANCE_CONSTRAINT, "edge_clearance", formatMinMax },
466  { HOLE_SIZE_CONSTRAINT, "hole_size", formatMinMax },
467  { COURTYARD_CLEARANCE_CONSTRAINT, "courtyard_clearance", formatMinMax },
468  { SILK_CLEARANCE_CONSTRAINT, "silk_clearance", formatMinMax },
469  { TRACK_WIDTH_CONSTRAINT, "track_width", formatMinMax },
470  { ANNULAR_WIDTH_CONSTRAINT, "annular_width", formatMinMax },
471  { DISALLOW_CONSTRAINT, "disallow", nullptr },
472  { VIA_DIAMETER_CONSTRAINT, "via_diameter", formatMinMax },
473  { LENGTH_CONSTRAINT, "length", formatMinMax },
474  { SKEW_CONSTRAINT, "skew", formatMinMax },
475  { VIA_COUNT_CONSTRAINT, "via_count", formatMinMax }
476  };
477 
478  for( FORMATTER& fmt : formats )
479  {
480  if( fmt.type == constraint.m_Type )
481  {
482  wxString rv = fmt.name + " ";
483 
484  if( fmt.formatter )
485  rv += fmt.formatter( constraint );
486 
487  return rv;
488  }
489  }
490 
491  return "?";
492 }
493 
494 
498 void DRC_ENGINE::loadRules( const wxFileName& aPath )
499 {
500  if( aPath.FileExists() )
501  {
502  std::vector<DRC_RULE*> rules;
503 
504  FILE* fp = wxFopen( aPath.GetFullPath(), wxT( "rt" ) );
505 
506  if( fp )
507  {
508  DRC_RULES_PARSER parser( fp, aPath.GetFullPath() );
509  parser.Parse( rules, m_reporter );
510  }
511 
512  // Copy the rules into the member variable afterwards so that if Parse() throws then
513  // the possibly malformed rules won't contaminate the current ruleset.
514 
515  for( DRC_RULE* rule : rules )
516  m_rules.push_back( rule );
517  }
518 }
519 
520 
522 {
523  ReportAux( wxString::Format( "Compiling Rules (%d rules): ",
524  (int) m_rules.size() ) );
525 
526  for( DRC_TEST_PROVIDER* provider : m_testProviders )
527  {
528  ReportAux( wxString::Format( "- Provider: '%s': ", provider->GetName() ) );
529  drc_dbg( 7, "do prov %s", provider->GetName() );
530 
531  for( DRC_CONSTRAINT_TYPE_T id : provider->GetConstraintTypes() )
532  {
533  drc_dbg( 7, "do id %d", id );
534 
535  if( m_constraintMap.find( id ) == m_constraintMap.end() )
536  m_constraintMap[ id ] = new std::vector<CONSTRAINT_WITH_CONDITIONS*>();
537 
538  for( DRC_RULE* rule : m_rules )
539  {
540  DRC_RULE_CONDITION* condition = nullptr;
541  bool compileOk = false;
542  std::vector<DRC_CONSTRAINT> matchingConstraints;
543  drc_dbg( 7, "Scan provider %s, rule %s", provider->GetName(), rule->m_Name );
544 
545  if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
546  {
547  condition = rule->m_Condition;
548  compileOk = condition->Compile( nullptr, 0, 0 ); // fixme
549  }
550 
551  for( const DRC_CONSTRAINT& constraint : rule->m_Constraints )
552  {
553  drc_dbg(7, "scan constraint id %d\n", constraint.m_Type );
554 
555  if( constraint.m_Type != id )
556  continue;
557 
559 
560  rcons->layerTest = rule->m_LayerCondition;
561  rcons->condition = condition;
562 
563  matchingConstraints.push_back( constraint );
564 
565  rcons->constraint = constraint;
566  rcons->parentRule = rule;
567  m_constraintMap[ id ]->push_back( rcons );
568  }
569 
570  if( !matchingConstraints.empty() )
571  {
572  ReportAux( wxString::Format( " |- Rule: '%s' ",
573  rule->m_Name ) );
574 
575  if( condition )
576  {
577  ReportAux( wxString::Format( " |- condition: '%s' compile: %s",
578  condition->GetExpression(),
579  compileOk ? "OK" : "ERROR" ) );
580  }
581 
582  for (const DRC_CONSTRAINT& constraint : matchingConstraints )
583  {
584  ReportAux( wxString::Format( " |- constraint: %s",
585  formatConstraint( constraint ) ) );
586  }
587  }
588  }
589  }
590  }
591 }
592 
593 
597 void DRC_ENGINE::InitEngine( const wxFileName& aRulePath )
598 {
600 
601  for( DRC_TEST_PROVIDER* provider : m_testProviders )
602  {
603  ReportAux( wxString::Format( "Create DRC provider: '%s'", provider->GetName() ) );
604  provider->SetDRCEngine( this );
605  }
606 
607  for( DRC_RULE* rule : m_rules )
608  delete rule;
609 
610  m_rules.clear();
611  m_rulesValid = false;
612 
613  for( std::pair< DRC_CONSTRAINT_TYPE_T,
614  std::vector<CONSTRAINT_WITH_CONDITIONS*>* > pair : m_constraintMap )
615  {
616  for( CONSTRAINT_WITH_CONDITIONS* constraintWithCondition : *pair.second )
617  delete constraintWithCondition;
618 
619  delete pair.second;
620  }
621 
622  m_constraintMap.clear();
623 
624  try // attempt to load full set of rules (implicit + user rules)
625  {
627  loadRules( aRulePath );
628  compileRules();
629  }
630  catch( PARSE_ERROR& original_parse_error )
631  {
632  try // try again with just our implicit rules
633  {
635  compileRules();
636  }
637  catch( PARSE_ERROR& ignore )
638  {
639  wxFAIL_MSG( "Compiling implict rules failed." );
640  }
641 
642  throw original_parse_error;
643  }
644 
645  for( int ii = DRCE_FIRST; ii < DRCE_LAST; ++ii )
646  m_errorLimits[ ii ] = INT_MAX;
647 
648  m_rulesValid = true;
649 }
650 
651 
652 void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints )
653 {
654  m_userUnits = aUnits;
655 
656  // Note: set these first. The phase counts may be dependent on some of them.
657  m_reportAllTrackErrors = aReportAllTrackErrors;
658  m_testFootprints = aTestFootprints;
659 
660  if( m_progressReporter )
661  {
662  int phases = 0;
663 
664  for( DRC_TEST_PROVIDER* provider : m_testProviders )
665  {
666  if( provider->IsEnabled() )
667  phases += provider->GetNumPhases();
668  }
669 
670  m_progressReporter->AddPhases( phases );
671  }
672 
673  for( int ii = DRCE_FIRST; ii < DRCE_LAST; ++ii )
674  {
675  if( m_designSettings->Ignore( ii ) )
676  m_errorLimits[ ii ] = 0;
677  else
678  m_errorLimits[ ii ] = INT_MAX;
679  }
680 
681  for( ZONE* zone : m_board->Zones() )
682  zone->CacheBoundingBox();
683 
684  for( FOOTPRINT* footprint : m_board->Footprints() )
685  {
686  for( ZONE* zone : footprint->Zones() )
687  zone->CacheBoundingBox();
688 
689  footprint->BuildPolyCourtyards();
690  }
691 
692  for( DRC_TEST_PROVIDER* provider : m_testProviders )
693  {
694  if( !provider->IsEnabled() )
695  continue;
696 
697  drc_dbg( 0, "Running test provider: '%s'\n", provider->GetName() );
698 
699  ReportAux( wxString::Format( "Run DRC provider: '%s'", provider->GetName() ) );
700 
701  if( !provider->Run() )
702  break;
703  }
704 }
705 
706 
708  const BOARD_ITEM* a, const BOARD_ITEM* b,
709  PCB_LAYER_ID aLayer, REPORTER* aReporter )
710 {
711 #define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
712 #define UNITS aReporter ? aReporter->GetUnits() : EDA_UNITS::MILLIMETRES
713  /*
714  * NOTE: all string manipulation MUST be kept inside the REPORT macro. It absolutely
715  * kills performance when running bulk DRC tests (where aReporter is nullptr).
716  */
717 
718  if( aConstraintId == CLEARANCE_CONSTRAINT )
719  {
720  // A PTH pad has a plated cylinder around the hole so copper clearances apply
721  // whether or not there's a flashed pad. Not true for NPTHs.
722  if( a->Type() == PCB_PAD_T )
723  {
724  const PAD* pad = static_cast<const PAD*>( a );
725 
726  if( pad->GetAttribute() == PAD_ATTRIB_NPTH && !pad->FlashLayer( aLayer ) )
727  aConstraintId = HOLE_CLEARANCE_CONSTRAINT;
728  }
729  }
730 
731  const BOARD_CONNECTED_ITEM* ac = a && a->IsConnected() ?
732  static_cast<const BOARD_CONNECTED_ITEM*>( a ) : nullptr;
733  const BOARD_CONNECTED_ITEM* bc = b && b->IsConnected() ?
734  static_cast<const BOARD_CONNECTED_ITEM*>( b ) : nullptr;
735 
736  bool a_is_non_copper = a && ( !a->IsOnCopperLayer() || isKeepoutZone( a, false ) );
737  bool b_is_non_copper = b && ( !b->IsOnCopperLayer() || isKeepoutZone( b, false ) );
738 
739  const DRC_CONSTRAINT* constraintRef = nullptr;
740  bool implicit = false;
741 
742  // Local overrides take precedence
743  if( aConstraintId == CLEARANCE_CONSTRAINT )
744  {
745  int overrideA = 0;
746  int overrideB = 0;
747 
748  if( ac && !b_is_non_copper && ac->GetLocalClearanceOverrides( nullptr ) > 0 )
749  {
750  overrideA = ac->GetLocalClearanceOverrides( &m_msg );
751 
752  REPORT( "" )
753  REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ),
755  EscapeHTML( MessageTextFromValue( UNITS, overrideA ) ) ) )
756  }
757 
758  if( bc && !a_is_non_copper && bc->GetLocalClearanceOverrides( nullptr ) > 0 )
759  {
760  overrideB = bc->GetLocalClearanceOverrides( &m_msg );
761 
762  REPORT( "" )
763  REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ),
765  EscapeHTML( MessageTextFromValue( UNITS, overrideB ) ) ) )
766  }
767 
768  if( overrideA || overrideB )
769  {
771  constraint.m_Value.SetMin( std::max( overrideA, overrideB ) );
772  return constraint;
773  }
774  }
775 
776  auto processConstraint =
777  [&]( const CONSTRAINT_WITH_CONDITIONS* c ) -> bool
778  {
779  implicit = c->parentRule && c->parentRule->m_Implicit;
780 
781  REPORT( "" )
782 
783  if( aConstraintId == CLEARANCE_CONSTRAINT )
784  {
785  int val = c->constraint.m_Value.Min();
786  REPORT( wxString::Format( _( "Checking %s; clearance: %s." ),
787  EscapeHTML( c->constraint.GetName() ),
788  EscapeHTML( MessageTextFromValue( UNITS, val ) ) ) )
789  }
790  else if( aConstraintId == COURTYARD_CLEARANCE_CONSTRAINT )
791  {
792  int val = c->constraint.m_Value.Min();
793  REPORT( wxString::Format( _( "Checking %s; courtyard clearance: %s." ),
794  EscapeHTML( c->constraint.GetName() ),
795  EscapeHTML( MessageTextFromValue( UNITS, val ) ) ) )
796  }
797  else if( aConstraintId == SILK_CLEARANCE_CONSTRAINT )
798  {
799  int val = c->constraint.m_Value.Min();
800  REPORT( wxString::Format( _( "Checking %s; silk clearance: %s." ),
801  EscapeHTML( c->constraint.GetName() ),
802  EscapeHTML( MessageTextFromValue( UNITS, val ) ) ) )
803  }
804  else if( aConstraintId == HOLE_CLEARANCE_CONSTRAINT )
805  {
806  int val = c->constraint.m_Value.Min();
807  REPORT( wxString::Format( _( "Checking %s; hole clearance: %s." ),
808  EscapeHTML( c->constraint.GetName() ),
809  EscapeHTML( MessageTextFromValue( UNITS, val ) ) ) )
810  }
811  else if( aConstraintId == EDGE_CLEARANCE_CONSTRAINT )
812  {
813  int val = c->constraint.m_Value.Min();
814  REPORT( wxString::Format( _( "Checking %s; edge clearance: %s." ),
815  EscapeHTML( c->constraint.GetName() ),
816  EscapeHTML( MessageTextFromValue( UNITS, val ) ) ) )
817  }
818  else
819  {
820  REPORT( wxString::Format( _( "Checking %s." ), c->constraint.GetName() ) )
821  }
822 
823  if( aConstraintId == CLEARANCE_CONSTRAINT )
824  {
825  if( implicit && ( a_is_non_copper || b_is_non_copper ) )
826  {
827  REPORT( _( "Board and netclass clearances apply only between copper items." ) );
828  return true;
829  }
830  }
831  else if( aConstraintId == DISALLOW_CONSTRAINT )
832  {
833  int mask;
834 
835  if( a->GetFlags() & HOLE_PROXY )
836  {
837  mask = DRC_DISALLOW_HOLES;
838  }
839  else if( a->Type() == PCB_VIA_T )
840  {
841  if( static_cast<const VIA*>( a )->GetViaType() == VIATYPE::BLIND_BURIED )
843  else if( static_cast<const VIA*>( a )->GetViaType() == VIATYPE::MICROVIA )
845  else
846  mask = DRC_DISALLOW_VIAS;
847  }
848  else
849  {
850  switch( a->Type() )
851  {
852  case PCB_TRACE_T: mask = DRC_DISALLOW_TRACKS; break;
853  case PCB_ARC_T: mask = DRC_DISALLOW_TRACKS; break;
854  case PCB_PAD_T: mask = DRC_DISALLOW_PADS; break;
855  case PCB_FOOTPRINT_T: mask = DRC_DISALLOW_FOOTPRINTS; break;
856  case PCB_SHAPE_T: mask = DRC_DISALLOW_GRAPHICS; break;
857  case PCB_FP_SHAPE_T: mask = DRC_DISALLOW_GRAPHICS; break;
858  case PCB_TEXT_T: mask = DRC_DISALLOW_TEXTS; break;
859  case PCB_FP_TEXT_T: mask = DRC_DISALLOW_TEXTS; break;
860  case PCB_ZONE_T: mask = DRC_DISALLOW_ZONES; break;
861  case PCB_FP_ZONE_T: mask = DRC_DISALLOW_ZONES; break;
862  case PCB_LOCATE_HOLE_T: mask = DRC_DISALLOW_HOLES; break;
863  default: mask = 0; break;
864  }
865  }
866 
867  if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
868  {
869  if( implicit )
870  REPORT( _( "Keepout constraint not met." ) )
871  else
872  REPORT( _( "Disallow constraint not met." ) )
873 
874  return false;
875  }
876 
877  if( !( c->layerTest & a->GetLayerSet() ).any() )
878  {
879  if( implicit )
880  {
881  REPORT( _( "Keepout layer(s) not matched." ) )
882  }
883  else if( c->parentRule )
884  {
885  REPORT( wxString::Format( _( "Rule layer \"%s\" not matched." ),
886  EscapeHTML( c->parentRule->m_LayerSource ) ) )
887  REPORT( "Rule ignored." )
888  }
889  else
890  {
891  REPORT( _( "Rule layer not matched." ) )
892  REPORT( "Rule ignored." )
893  }
894 
895  return false;
896  }
897  }
898 
899  if( aLayer != UNDEFINED_LAYER && !c->layerTest.test( aLayer ) )
900  {
901  if( implicit )
902  {
903  REPORT( "Constraint layer not matched." )
904  }
905  else if( c->parentRule )
906  {
907  REPORT( wxString::Format( _( "Rule layer \"%s\" not matched." ),
908  EscapeHTML( c->parentRule->m_LayerSource ) ) )
909  REPORT( "Rule ignored." )
910  }
911  else
912  {
913  REPORT( _( "Rule layer not matched." ) )
914  REPORT( "Rule ignored." )
915  }
916 
917  return false;
918  }
919 
920  if( !c->condition || c->condition->GetExpression().IsEmpty() )
921  {
922  REPORT( implicit ? _( "Unconditional constraint applied." )
923  : _( "Unconditional rule applied." ) );
924 
925  constraintRef = &c->constraint;
926  return true;
927  }
928  else
929  {
930  if( implicit )
931  {
932  // Don't report on implicit rule conditions; they're synthetic.
933  }
934  else
935  {
936  REPORT( wxString::Format( _( "Checking rule condition \"%s\"." ),
937  EscapeHTML( c->condition->GetExpression() ) ) )
938  }
939 
940  if( c->condition->EvaluateFor( a, b, aLayer, aReporter ) )
941  {
942  REPORT( implicit ? _( "Constraint applied." )
943  : _( "Rule applied; overrides previous constraints." ) )
944 
945  constraintRef = &c->constraint;
946  return true;
947  }
948  else
949  {
950  REPORT( implicit ? _( "Membership not satisfied; constraint ignored." )
951  : _( "Condition not satisfied; rule ignored." ) )
952 
953  return false;
954  }
955  }
956  };
957 
958  if( m_constraintMap.count( aConstraintId ) )
959  {
960  std::vector<CONSTRAINT_WITH_CONDITIONS*>* ruleset = m_constraintMap[ aConstraintId ];
961 
962  if( aReporter )
963  {
964  // We want to see all results so process in "natural" order
965  for( int ii = 0; ii < (int) ruleset->size(); ++ii )
966  {
967  processConstraint( ruleset->at( ii ) );
968  }
969  }
970  else
971  {
972  // Last matching rule wins, so process in reverse order and quit when match found
973  for( int ii = (int) ruleset->size() - 1; ii >= 0; --ii )
974  {
975  if( processConstraint( ruleset->at( ii ) ) )
976  break;
977  }
978  }
979  }
980 
981  bool explicitConstraintFound = constraintRef && !implicit;
982 
983  // Unfortunately implicit rules don't work for local clearances (such as zones) because
984  // they have to be max'ed with netclass values (which are already implicit rules), and our
985  // rule selection paradigm is "winner takes all".
986  if( aConstraintId == CLEARANCE_CONSTRAINT && !explicitConstraintFound )
987  {
988  int global = constraintRef ? constraintRef->m_Value.Min() : 0;
989  int localA = ac ? ac->GetLocalClearance( nullptr ) : 0;
990  int localB = bc ? bc->GetLocalClearance( nullptr ) : 0;
991  int clearance = global;
992 
993  if( localA > 0 )
994  {
995  REPORT( "" )
996  REPORT( wxString::Format( _( "Local clearance on %s; clearance: %s." ),
998  EscapeHTML( MessageTextFromValue( UNITS, localA ) ) ) )
999 
1000  if( localA > clearance )
1001  clearance = ac->GetLocalClearance( &m_msg );
1002  }
1003 
1004  if( localB > 0 )
1005  {
1006  REPORT( "" )
1007  REPORT( wxString::Format( _( "Local clearance on %s; clearance: %s." ),
1009  EscapeHTML( MessageTextFromValue( UNITS, localB ) ) ) )
1010 
1011  if( localB > clearance )
1012  clearance = bc->GetLocalClearance( &m_msg );
1013  }
1014 
1015  if( localA > global || localB > global )
1016  {
1017  DRC_CONSTRAINT constraint( CLEARANCE_CONSTRAINT, m_msg );
1018  constraint.m_Value.SetMin( clearance );
1019  return constraint;
1020  }
1021  }
1022 
1023  static DRC_CONSTRAINT nullConstraint( NULL_CONSTRAINT );
1024  nullConstraint.m_DisallowFlags = 0;
1025 
1026  return constraintRef ? *constraintRef : nullConstraint;
1027 
1028 #undef REPORT
1029 #undef UNITS
1030 }
1031 
1032 
1033 bool DRC_ENGINE::IsErrorLimitExceeded( int error_code )
1034 {
1035  assert( error_code >= 0 && error_code <= DRCE_LAST );
1036  return m_errorLimits[ error_code ] <= 0;
1037 }
1038 
1039 
1040 void DRC_ENGINE::ReportViolation( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos )
1041 {
1042  m_errorLimits[ aItem->GetErrorCode() ] -= 1;
1043 
1044  if( m_violationHandler )
1045  m_violationHandler( aItem, aPos );
1046 
1047  if( m_reporter )
1048  {
1049  wxString msg = wxString::Format( "Test '%s': %s (code %d)",
1050  aItem->GetViolatingTest()->GetName(),
1051  aItem->GetErrorMessage(),
1052  aItem->GetErrorCode() );
1053 
1054  DRC_RULE* rule = aItem->GetViolatingRule();
1055 
1056  if( rule )
1057  msg += wxString::Format( ", violating rule: '%s'", rule->m_Name );
1058 
1059  m_reporter->Report( msg );
1060 
1061  wxString violatingItemsStr = "Violating items: ";
1062 
1063  m_reporter->Report( wxString::Format( " |- violating position (%d, %d)",
1064  aPos.x,
1065  aPos.y ) );
1066  }
1067 }
1068 
1069 void DRC_ENGINE::ReportAux ( const wxString& aStr )
1070 {
1071  if( !m_reporter )
1072  return;
1073 
1075 }
1076 
1077 
1078 bool DRC_ENGINE::ReportProgress( double aProgress )
1079 {
1080  if( !m_progressReporter )
1081  return true;
1082 
1083  m_progressReporter->SetCurrentProgress( aProgress );
1084  return m_progressReporter->KeepRefreshing( false );
1085 }
1086 
1087 
1088 bool DRC_ENGINE::ReportPhase( const wxString& aMessage )
1089 {
1090  if( !m_progressReporter )
1091  return true;
1092 
1093  m_progressReporter->AdvancePhase( aMessage );
1094  return m_progressReporter->KeepRefreshing( false );
1095 }
1096 
1097 
1098 #if 0
1099 DRC_CONSTRAINT DRC_ENGINE::GetWorstGlobalConstraint( DRC_CONSTRAINT_TYPE_T ruleID )
1100 {
1101  DRC_CONSTRAINT rv;
1102 
1103  rv.m_Value.SetMin( std::numeric_limits<int>::max() );
1104  rv.m_Value.SetMax( std::numeric_limits<int>::min() );
1105  for( auto rule : QueryRulesById( ruleID ) )
1106  {
1107  auto mm = rule->GetConstraint().m_Value;
1108  if( mm.HasMax() )
1109  rv.m_Value.SetMax( std::max( mm.Max(), rv.m_Value.Max() ) );
1110  if( mm.HasMin() )
1111  rv.m_Value.SetMin( std::min( mm.Min(), rv.m_Value.Min() ) );
1112  }
1113 
1114  return rv;
1115 }
1116 #endif
1117 
1118 
1119 std::vector<DRC_CONSTRAINT> DRC_ENGINE::QueryConstraintsById( DRC_CONSTRAINT_TYPE_T constraintID )
1120 {
1121  std::vector<DRC_CONSTRAINT> rv;
1122 
1123  if( m_constraintMap.count( constraintID ) )
1124  {
1125  for ( CONSTRAINT_WITH_CONDITIONS* c : *m_constraintMap[constraintID] )
1126  rv.push_back( c->constraint );
1127  }
1128 
1129  return rv;
1130 }
1131 
1132 
1134 {
1135  //drc_dbg(10,"hascorrect id %d size %d\n", ruleID, m_ruleMap[ruleID]->sortedRules.size( ) );
1136  if( m_constraintMap.count( constraintID ) )
1137  return m_constraintMap[ constraintID ]->size() > 0;
1138 
1139  return false;
1140 }
1141 
1142 
1144  DRC_CONSTRAINT& aConstraint )
1145 {
1146  int worst = 0;
1147 
1148  for( const DRC_CONSTRAINT& constraint : QueryConstraintsById( aConstraintId ) )
1149  {
1150  if( constraint.GetValue().HasMin() )
1151  {
1152  int current = constraint.GetValue().Min();
1153 
1154  if( current > worst )
1155  {
1156  worst = current;
1157  aConstraint = constraint;
1158  }
1159  }
1160  }
1161 
1162  return worst > 0;
1163 }
1164 
1165 
1166 // fixme: move two functions below to pcbcommon?
1167 static int matchDpSuffix( const wxString& aNetName, wxString& aComplementNet,
1168  wxString& aBaseDpName )
1169 {
1170  int rv = 0;
1171 
1172  if( aNetName.EndsWith( "+" ) )
1173  {
1174  aComplementNet = "-";
1175  rv = 1;
1176  }
1177  else if( aNetName.EndsWith( "P" ) )
1178  {
1179  aComplementNet = "N";
1180  rv = 1;
1181  }
1182  else if( aNetName.EndsWith( "-" ) )
1183  {
1184  aComplementNet = "+";
1185  rv = -1;
1186  }
1187  else if( aNetName.EndsWith( "N" ) )
1188  {
1189  aComplementNet = "P";
1190  rv = -1;
1191  }
1192  // Match P followed by 2 digits
1193  else if( aNetName.Right( 2 ).IsNumber() && aNetName.Right( 3 ).Left( 1 ) == "P" )
1194  {
1195  aComplementNet = "N" + aNetName.Right( 2 );
1196  rv = 1;
1197  }
1198  // Match P followed by 1 digit
1199  else if( aNetName.Right( 1 ).IsNumber() && aNetName.Right( 2 ).Left( 1 ) == "P" )
1200  {
1201  aComplementNet = "N" + aNetName.Right( 1 );
1202  rv = 1;
1203  }
1204  // Match N followed by 2 digits
1205  else if( aNetName.Right( 2 ).IsNumber() && aNetName.Right( 3 ).Left( 1 ) == "N" )
1206  {
1207  aComplementNet = "P" + aNetName.Right( 2 );
1208  rv = -1;
1209  }
1210  // Match N followed by 1 digit
1211  else if( aNetName.Right( 1 ).IsNumber() && aNetName.Right( 2 ).Left( 1 ) == "N" )
1212  {
1213  aComplementNet = "P" + aNetName.Right( 1 );
1214  rv = -1;
1215  }
1216  if( rv != 0 )
1217  {
1218  aBaseDpName = aNetName.Left( aNetName.Length() - aComplementNet.Length() );
1219  aComplementNet = aBaseDpName + aComplementNet;
1220  }
1221 
1222  return rv;
1223 }
1224 
1225 
1226 int DRC_ENGINE::IsNetADiffPair( BOARD* aBoard, NETINFO_ITEM* aNet, int& aNetP, int& aNetN )
1227 {
1228  wxString refName = aNet->GetNetname();
1229  wxString dummy, coupledNetName;
1230 
1231  if( int polarity = matchDpSuffix( refName, coupledNetName, dummy ) )
1232  {
1233  NETINFO_ITEM* net = aBoard->FindNet( coupledNetName );
1234 
1235  if( !net )
1236  return false;
1237 
1238  if( polarity > 0 )
1239  {
1240  aNetP = aNet->GetNet();
1241  aNetN = net->GetNet();
1242  }
1243  else
1244  {
1245  aNetP = net->GetNet();
1246  aNetN = aNet->GetNet();
1247  }
1248 
1249  return true;
1250  }
1251 
1252  return false;
1253 }
1254 
1255 
1257 {
1258  for( auto prov : m_testProviders )
1259  if( name == prov->GetName() )
1260  return prov;
1261 
1262  return nullptr;
1263 }
DRC_TEST_PROVIDER * GetTestProvider(const wxString &name) const
virtual void AdvancePhase()
Uses the next vailable virtual zone of the dialog progress bar.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1234
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Definition: base_units.cpp:123
EDA_UNITS m_userUnits
Definition: drc_engine.h:208
#define UNITS
void loadRules(const wxFileName &aPath)
Loads and parses a rule set from an sexpr text file.
Definition: drc_engine.cpp:498
class FP_TEXT, text in a footprint
Definition: typeinfo.h:93
bool GetDoNotAllowFootprints() const
Definition: zone.h:752
std::vector< int > m_errorLimits
Definition: drc_engine.h:209
ZONES & Zones()
Definition: board.h:289
bool ReportPhase(const wxString &aMessage)
DRC_RULE_CONDITION * m_Condition
Definition: drc_rule.h:99
std::vector< DRC_TEST_PROVIDER * > m_testProviders
Definition: drc_engine.h:206
bool m_Implicit
Definition: drc_rule.h:95
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:747
void SetMin(T v)
Definition: minoptmax.h:39
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
Definition: board_item.h:86
MINOPTMAX< int > & Value()
Definition: drc_rule.h:122
std::vector< DRC_TEST_PROVIDER * > GetTestProviders() const
wxString m_Name
Definition: drc_rule.h:96
void SetOpt(T v)
Definition: minoptmax.h:41
static DRC_TEST_PROVIDER_REGISTRY & Instance()
void compileRules()
Definition: drc_engine.cpp:521
static int matchDpSuffix(const wxString &aNetName, wxString &aComplementNet, wxString &aBaseDpName)
bool GetDoNotAllowVias() const
Definition: zone.h:749
bool IsErrorLimitExceeded(int error_code)
std::vector< DRC_CONSTRAINT > QueryConstraintsById(DRC_CONSTRAINT_TYPE_T ruleID)
bool Ignore(int aDRCErrorCode)
returns true if the DRC error code's severity is SEVERITY_IGNORE
bool m_testFootprints
Definition: drc_engine.h:211
bool QueryWorstConstraint(DRC_CONSTRAINT_TYPE_T aRuleId, DRC_CONSTRAINT &aConstraint)
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
static int IsNetADiffPair(BOARD *aBoard, NETINFO_ITEM *aNet, int &aNetP, int &aNetN)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:559
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
class PAD, a pad in a footprint
Definition: typeinfo.h:90
bool m_rulesValid
Definition: drc_engine.h:205
virtual int GetLocalClearanceOverrides(wxString *aSource) const
Function GetLocalClearanceOverrides returns any local clearance overrides set in the "classic" (ie: p...
T Min() const
Definition: minoptmax.h:31
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected and have...
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
T Max() const
Definition: minoptmax.h:32
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
BOARD_DESIGN_SETTINGS * m_designSettings
Definition: drc_engine.h:199
PAD_ATTR_T GetAttribute() const
Definition: pad.h:348
MINOPTMAX< int > m_Value
Definition: drc_rule.h:142
wxString GetExpression() const
void SynchronizeNetsAndNetClasses()
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1379
bool GetDoNotAllowPads() const
Definition: zone.h:751
virtual void SetCurrentProgress(double aProgress)
Set the progress value to aProgress (0..1)
PCB_LAYER_ID
A quick note on layer IDs:
bool GetDoNotAllowCopperPour() const
Definition: zone.h:748
bool FlashLayer(int aLayer) const
Definition: pcbnew/pad.cpp:189
LSET is a set of PCB_LAYER_IDs.
void addRule(DRC_RULE *rule)
Definition: drc_engine.h:172
std::vector< DRC_RULE * > m_rules
Definition: drc_engine.h:204
std::vector< DRC_CONSTRAINT > m_Constraints
Definition: drc_rule.h:100
void drcPrintDebugMessage(int level, const wxString &msg, const char *function, int line)
Definition: drc_engine.cpp:36
FOOTPRINTS & Footprints()
Definition: board.h:283
bool GetDoNotAllowTracks() const
Definition: zone.h:750
void Parse(std::vector< DRC_RULE * > &aRules, REPORTER *aReporter)
void SetMax(T v)
Definition: minoptmax.h:40
bool ReportProgress(double aProgress)
const wxString & GetNetname() const
Function GetNetname.
Definition: netinfo.h:231
bool HasRulesForConstraintType(DRC_CONSTRAINT_TYPE_T constraintID)
NETCLASSES & GetNetClasses() const
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
class ZONE, a copper pour area
Definition: typeinfo.h:106
PROGRESS_REPORTER * m_progressReporter
Definition: drc_engine.h:219
DRC_CONSTRAINT_TYPE_T m_Type
Definition: drc_rule.h:141
static bool isKeepoutZone(const BOARD_ITEM *aItem, bool aCheckFlags)
Definition: drc_engine.cpp:87
REPORTER * m_reporter
Definition: drc_engine.h:218
static wxString formatConstraint(const DRC_CONSTRAINT &constraint)
Definition: drc_engine.cpp:433
class FOOTPRINT, a footprint
Definition: typeinfo.h:89
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
Definition: eda_item.h:127
EDA_UNITS
Definition: eda_units.h:38
DRC_ENGINE(BOARD *aBoard=nullptr, BOARD_DESIGN_SETTINGS *aSettings=nullptr)
Definition: drc_engine.cpp:52
DRC_TEST_PROVIDER is a base class that represents a DRC "provider" which runs some DRC functions over...
DRC_RULE * createImplicitRule(const wxString &name)
Definition: drc_engine.cpp:116
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
Struct PARSE_ERROR contains a filename or source description, a problem input line,...
Definition: ki_exception.h:123
const char * name
Definition: DXF_plotter.cpp:59
DRC_CONSTRAINT_TYPE_T
Definition: drc_rule.h:41
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
LSET m_LayerCondition
Definition: drc_rule.h:98
int GetNet() const
Function GetNet.
Definition: netinfo.h:223
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:186
#define _(s)
Definition: 3d_actions.cpp:33
void ReportAux(const wxString &aStr)
int GetClearance() const
Definition: netclass.h:159
virtual wxString GetSelectMenuText(EDA_UNITS aUnits) const
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: eda_item.cpp:123
void AddConstraint(DRC_CONSTRAINT &aConstraint)
Definition: drc_rule.cpp:46
std::unordered_map< DRC_CONSTRAINT_TYPE_T, std::vector< CONSTRAINT_WITH_CONDITIONS * > * > m_constraintMap
Definition: drc_engine.h:215
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
class ZONE, managed by a footprint
Definition: typeinfo.h:95
NETCLASS * GetDefault() const
Function GetDefault.
wxString m_msg
Definition: drc_engine.h:221
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints)
Runs the DRC tests.
Definition: drc_engine.cpp:652
int m_DisallowFlags
Definition: drc_rule.h:143
DRC_VIOLATION_HANDLER m_violationHandler
Definition: drc_engine.h:217
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
BOARD * m_board
Definition: drc_engine.h:200
NETCLASSPTR GetDefault() const
Function GetDefault.
Definition: netclass.h:266
virtual bool IsConnected() const
Function IsConnected() Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:146
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
DRC_CONSTRAINT EvalRulesForItems(DRC_CONSTRAINT_TYPE_T ruleID, const BOARD_ITEM *a, const BOARD_ITEM *b=nullptr, PCB_LAYER_ID aLayer=UNDEFINED_LAYER, REPORTER *aReporter=nullptr)
Definition: drc_engine.cpp:707
bool m_MicroViasAllowed
true to allow micro vias
#define drc_dbg(level, fmt,...)
Definition: drc_engine.h:55
Definition: pad.h:59
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
Definition: string.cpp:341
void loadImplicitRules()
Definition: drc_engine.cpp:129
STATUS_FLAGS GetFlags() const
Definition: eda_item.h:222
bool m_reportAllTrackErrors
Definition: drc_engine.h:210
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, wxPoint aPos)
void AddPhases(int aNumPhases)
virtual int GetLocalClearance(wxString *aSource) const
Function GetLocalClearance returns any local clearances set in the "classic" (ie: pre-rule) system.
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:91
virtual bool IsOnCopperLayer() const
Definition: board_item.h:154
void InitEngine(const wxFileName &aRulePath)
Initializes the DRC engine.
Definition: drc_engine.cpp:597
virtual LSET GetLayerSet() const
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:191
KICAD_T Type() const
Function Type()
Definition: eda_item.h:181
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.