51#define ERROR_LIMIT 199
52#define EXTENDED_ERROR_LIMIT 499
69 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
71 int setLevel = wxAtoi( valueStr );
73 if( level <= setLevel )
74 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
117 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
143 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
146 rule->m_Implicit =
true;
164 rule->AddConstraint( widthConstraint );
168 rule->AddConstraint( connectionConstraint );
172 rule->AddConstraint( drillConstraint );
176 rule->AddConstraint( annulusConstraint );
180 rule->AddConstraint( diameterConstraint );
184 rule->AddConstraint( holeToHoleConstraint );
189 rule->AddConstraint( thermalSpokeCountConstraint );
195 rule->AddConstraint( silkClearanceConstraint );
201 rule->AddConstraint( silkTextHeightConstraint );
207 rule->AddConstraint( silkTextThicknessConstraint );
212 rule->AddConstraint( holeClearanceConstraint );
217 rule->AddConstraint( edgeClearanceConstraint );
222 rule->AddConstraint( courtyardClearanceConstraint );
226 std::shared_ptr<DRC_RULE> uViaRule =
createImplicitRule(
_(
"board setup micro-via constraints" ) );
232 uViaRule->AddConstraint( uViaDrillConstraint );
236 uViaRule->AddConstraint( uViaDiameterConstraint );
240 std::shared_ptr<DRC_RULE> barcodeRule =
createImplicitRule(
_(
"barcode visual separation default" ) );
243 barcodeRule->AddConstraint( barcodeSeparationConstraint );
248 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
249 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
251 auto makeNetclassRules =
252 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
254 wxString ncName = nc->GetName();
257 ncName.Replace(
"'",
"\\'" );
259 if( nc->HasClearance() )
261 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
262 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
263 nc->GetClearanceParent()->GetHumanReadableName() );
264 netclassRule->m_Implicit =
true;
266 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
268 netclassClearanceRules.push_back( netclassRule );
272 netclassRule->AddConstraint( constraint );
275 if( nc->HasTrackWidth() )
277 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
278 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
279 nc->GetTrackWidthParent()->GetHumanReadableName() );
280 netclassRule->m_Implicit =
true;
282 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
284 netclassClearanceRules.push_back( netclassRule );
289 netclassRule->AddConstraint( constraint );
292 if( nc->HasDiffPairWidth() )
294 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
295 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
296 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
297 netclassRule->m_Implicit =
true;
299 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
301 netclassItemSpecificRules.push_back( netclassRule );
305 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
306 netclassRule->AddConstraint( constraint );
309 if( nc->HasDiffPairGap() )
311 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
312 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
313 nc->GetDiffPairGapParent()->GetHumanReadableName() );
314 netclassRule->m_Implicit =
true;
316 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
318 netclassItemSpecificRules.push_back( netclassRule );
323 netclassRule->AddConstraint( constraint );
326 if( nc->GetDiffPairGap() < nc->GetClearance() )
328 netclassRule = std::make_shared<DRC_RULE>();
329 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
330 nc->GetDiffPairGapParent()->GetHumanReadableName() );
331 netclassRule->m_Implicit =
true;
333 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
335 netclassItemSpecificRules.push_back( netclassRule );
338 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
339 netclassRule->AddConstraint( min_clearanceConstraint );
343 if( nc->HasViaDiameter() )
345 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
346 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
347 nc->GetViaDiameterParent()->GetHumanReadableName() );
348 netclassRule->m_Implicit =
true;
350 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
352 netclassItemSpecificRules.push_back( netclassRule );
357 netclassRule->AddConstraint( constraint );
360 if( nc->HasViaDrill() )
362 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
363 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
364 nc->GetViaDrillParent()->GetHumanReadableName() );
365 netclassRule->m_Implicit =
true;
367 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
369 netclassItemSpecificRules.push_back( netclassRule );
374 netclassRule->AddConstraint( constraint );
377 if( nc->HasuViaDiameter() )
379 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
380 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
381 nc->GetuViaDiameterParent()->GetHumanReadableName() );
382 netclassRule->m_Implicit =
true;
384 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
386 netclassItemSpecificRules.push_back( netclassRule );
390 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
391 netclassRule->AddConstraint( constraint );
394 if( nc->HasuViaDrill() )
396 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
397 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
398 nc->GetuViaDrillParent()->GetHumanReadableName() );
399 netclassRule->m_Implicit =
true;
401 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
403 netclassItemSpecificRules.push_back( netclassRule );
408 netclassRule->AddConstraint( constraint );
412 m_board->SynchronizeNetsAndNetClasses(
false );
416 makeNetclassRules( netclass,
false );
419 makeNetclassRules( netclass,
false );
426 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
427 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
429 return lhs->m_Constraints[0].m_Value.Min()
430 < rhs->m_Constraints[0].m_Value.Min();
433 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
436 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
441 std::vector<ZONE*> keepoutZones;
446 keepoutZones.push_back( zone );
451 for(
ZONE* zone : footprint->Zones() )
454 keepoutZones.push_back( zone );
458 for(
ZONE* zone : keepoutZones )
460 wxString
name = zone->GetZoneName();
467 rule->m_ImplicitItemId = zone->m_Uuid;
469 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsArea('%s')" ),
470 zone->m_Uuid.AsString() ) );
472 rule->m_LayerCondition = zone->GetLayerSet();
474 int disallowFlags = 0;
476 if( zone->GetDoNotAllowTracks() )
479 if( zone->GetDoNotAllowVias() )
482 if( zone->GetDoNotAllowPads() )
485 if( zone->GetDoNotAllowZoneFills() )
488 if( zone->GetDoNotAllowFootprints() )
493 rule->AddConstraint( disallowConstraint );
500 if( aPath.FileExists() )
502 std::vector<std::shared_ptr<DRC_RULE>> rules;
504 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
509 std::function<bool( wxString* )>
resolver =
510 [&]( wxString* token ) ->
bool
513 return m_board->GetProject()->TextVarResolver( token );
518 while(
char* line = lineReader.
ReadLine() )
528 for( std::shared_ptr<DRC_RULE>& rule : rules )
541 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
545 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
547 condition = rule->m_Condition;
548 condition->
Compile( &error_semaphore );
553 TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
562 engineConstraint->
layerTest = rule->m_LayerCondition;
579 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
581 provider->SetDRCEngine(
this );
616 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
619 throw original_parse_error;
656 if( !cacheGenerator.
Run() )
660 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
662 int timestamp =
m_board->GetTimeStamp();
667 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
669 if( !provider->RunTests( aUnits ) )
678 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
682#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
690 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
698 pad =
static_cast<const PAD*
>( a );
700 pad =
static_cast<const PAD*
>( b );
708 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
736 const ZONE* zone =
nullptr;
737 const FOOTPRINT* parentFootprint =
nullptr;
747 pad =
static_cast<const PAD*
>( a );
749 zone =
static_cast<const ZONE*
>( a );
752 pad =
static_cast<const PAD*
>( b );
754 zone =
static_cast<const ZONE*
>( b );
757 parentFootprint =
pad->GetParentFootprint();
761 constraint.
m_Type = aConstraintType;
763 auto applyConstraint =
766 if( c->constraint.m_Value.HasMin() )
768 if( c->parentRule && c->parentRule->m_Implicit )
774 if( c->constraint.m_Value.HasOpt() )
777 if( c->constraint.m_Value.HasMax() )
780 switch( c->constraint.m_Type )
815 && ( ( ( !ac ) ^ ( !bc ) )
818 || ( ( footprints[0] == footprints[1] )
821 && !b_is_non_copper )
828 for(
int ii = 0; ii < 2; ++ii )
831 if( !footprints[ii] || !alt_items[ii] )
834 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
836 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
838 if( it != netcodes.end() )
841 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
842 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
844 constraint.
SetName(
_(
"net tie" ) );
854 int override_val = 0;
855 std::optional<int> overrideA;
856 std::optional<int> overrideB;
858 if( ac && !b_is_non_copper )
861 if( bc && !a_is_non_copper )
864 if( overrideA.has_value() || overrideB.has_value() )
868 if( overrideA.has_value() )
871 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
878 if( overrideB.has_value() )
881 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
885 if( overrideB > override_val )
893 if( override_val < m_designSettings->m_MinClearance )
896 msg =
_(
"board minimum" );
899 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
905 if( override_val < m_designSettings->m_HoleClearance )
908 msg =
_(
"board minimum hole" );
911 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
930 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
941 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
944 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
947 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
958 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
961 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
964 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
973 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
985 std::optional<int>
override;
988 override =
pad->GetLocalSolderMaskMargin();
990 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
997 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1007 std::optional<int>
override;
1010 override =
pad->GetLocalSolderPasteMargin();
1015 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1025 std::optional<double> overrideRatio;
1028 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1033 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1042 auto testAssertion =
1045 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1046 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1048 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer,
1051 REPORT(
_(
"Assertion passed." ) )
1059 auto processConstraint =
1062 bool implicit = c->parentRule && c->parentRule->m_Implicit;
1066 switch( c->constraint.m_Type )
1075 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1080 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1085 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1091 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1097 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1103 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1109 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1115 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute cleraance: %s." ),
1121 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1127 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1130 c->constraint.m_Value.Min() ) ) )
1134 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1152 wxString min = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1153 wxString opt = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1154 wxString max = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1161 switch( c->constraint.m_Type )
1164 if( c->constraint.m_Value.HasOpt() )
1166 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1170 else if( c->constraint.m_Value.HasMin() )
1172 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1180 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1186 if( c->constraint.m_Value.HasOpt() )
1188 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1192 else if( c->constraint.m_Value.HasMin() )
1194 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1201 if( c->constraint.m_Value.HasOpt() )
1203 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1207 else if( c->constraint.m_Value.HasMin() )
1209 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1219 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1225 if( c->constraint.m_Value.HasOpt() )
1227 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1231 else if( c->constraint.m_Value.HasMin() )
1233 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1241 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1247 REPORT( wxString::Format(
_(
"Checking %s." ),
1253 if( c->constraint.m_Value.HasMin() )
1256 if( c->constraint.m_Value.HasOpt() )
1259 if( c->constraint.m_Value.HasMax() )
1262 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1273 REPORT( wxString::Format(
_(
"Checking %s." ),
1279 if( a_is_non_copper || b_is_non_copper )
1283 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1285 else if( a_is_non_copper )
1287 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1290 else if( b_is_non_copper )
1292 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1311 if(
via->IsMicroVia() )
1313 else if(
via->IsBlindVia() )
1315 else if(
via->IsBuriedVia() )
1337 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1345 default: mask = 0;
break;
1349 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1352 REPORT(
_(
"Keepout constraint not met." ) )
1354 REPORT(
_(
"Disallow constraint not met." ) )
1372 if( !( c->layerTest & itemLayers ).any() )
1376 REPORT(
_(
"Keepout layer(s) not matched." ) )
1378 else if( c->parentRule )
1380 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1381 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1385 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1393 || (
m_board->GetEnabledLayers() & c->layerTest ).count() == 0 )
1397 REPORT(
_(
"Constraint layer not matched." ) )
1399 else if( c->parentRule )
1401 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1402 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1406 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1413 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1416 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1422 REPORT(
_(
"Unconditional constraint applied." ) )
1426 REPORT(
_(
"Unconditional rule applied." ) )
1431 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1435 applyConstraint( c );
1445 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1446 EscapeHTML( c->condition->GetExpression() ) ) )
1449 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1455 REPORT(
_(
"Constraint applied." ) )
1459 REPORT(
_(
"Rule applied." ) )
1464 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1468 applyConstraint( c );
1472 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1473 :
_(
"Condition not satisfied; rule ignored." ) )
1480 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1483 processConstraint( rule );
1500 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
1504 a = parentFootprint;
1506 b = parentFootprint;
1510 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1513 processConstraint( rule );
1523 constraint.
SetName(
_(
"board setup" ) );
1530 constraint.
SetName(
_(
"board setup" ) );
1537 constraint.
SetName(
_(
"board setup" ) );
1550 bool needBlankLine =
true;
1559 needBlankLine =
false;
1562 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1583 needBlankLine =
false;
1586 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1600 if( !a_is_non_copper && !b_is_non_copper )
1605 needBlankLine =
false;
1608 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1614 constraint.
SetName(
_(
"board minimum" ) );
1624 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1630 constraint.
SetName(
_(
"board minimum" ) );
1638 if(
pad && parentFootprint )
1645 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
1650 constraint.
SetName(
_(
"footprint" ) );
1661 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
1678 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
1695 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
1725 auto testAssertion =
1728 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
1729 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1731 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1734 REPORT(
_(
"Assertion passed." ) )
1739 aFailureHandler( &c->constraint );
1743 auto processConstraint =
1747 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
1751 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1752 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1755 if( !c->condition || c->condition->GetExpression().IsEmpty() )
1757 REPORT(
_(
"Unconditional rule applied." ) )
1762 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1763 EscapeHTML( c->condition->GetExpression() ) ) )
1765 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1768 REPORT(
_(
"Rule applied." ) )
1773 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
1782 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1783 processConstraint( ruleset->at( ii ) );
1793 assert( error_code >= 0 && error_code <=
DRCE_LAST );
1799 int aMarkerLayer,
const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
1801 static std::mutex globalLock;
1807 std::lock_guard<std::mutex> guard( globalLock );
1813 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
1814 aItem->GetViolatingTest()->GetName(),
1815 aItem->GetErrorMessage(),
1816 aItem->GetErrorCode() );
1818 DRC_RULE* rule = aItem->GetViolatingRule();
1821 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
1825 wxString violatingItemsStr = wxT(
"Violating items: " );
1827 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
1874 wxSafeYield(
nullptr,
true );
1904 int current = c->constraint.GetValue().Min();
1906 if( current > worst )
1909 aConstraint = c->constraint;
1920 std::set<int> distinctMinimums;
1925 distinctMinimums.emplace( c->constraint.GetValue().Min() );
1928 return distinctMinimums;
1934 wxString& aBaseDpName )
1939 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
1943 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
1947 else if( ch ==
'+' )
1949 aComplementNet = wxT(
"-" );
1952 else if( ch ==
'-' )
1954 aComplementNet = wxT(
"+" );
1957 else if( ch ==
'N' )
1959 aComplementNet = wxT(
"P" );
1962 else if ( ch ==
'P' )
1964 aComplementNet = wxT(
"N" );
1973 if( rv != 0 && count >= 1 )
1975 aBaseDpName = aNetName.Left( aNetName.Length() - count );
1976 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
1986 wxString
dummy, coupledNetName;
2022 if( parentFootprint && parentFootprint->
IsNetTie() )
2029 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2031 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2045 if(
name == prov->GetName() )
2057 std::vector<BOARD_ITEM*> matches;
2069 for(
auto& [kiid, item] :
m_board->GetItemByIdCache() )
2071 LSET itemLayers = item->GetLayerSet();
2075 if( condition.
EvaluateFor( item,
nullptr,
static_cast<int>( aConstraint ), layer,
2078 matches.push_back( item );
constexpr EDA_IU_SCALE pcbIUScale
constexpr EDA_IU_SCALE unityScale
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
#define MAXIMUM_CLEARANCE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual std::optional< int > GetClearanceOverrides(wxString *aSource) const
Return any clearance overrides set in the "classic" (ie: pre-rule) system.
virtual std::optional< int > GetLocalClearance() const
Return any local clearances set in the "classic" (ie: pre-rule) system.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
int m_CopperEdgeClearance
int m_MinSilkTextThickness
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
int m_ViasMinAnnularWidth
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
virtual bool HasDrilledHole() const
virtual bool IsOnCopperLayer() const
Information pertinent to a Pcbnew printed circuit board.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
void SetParentRule(DRC_RULE *aParentRule)
MINOPTMAX< int > & Value()
ZONE_CONNECTION m_ZoneConnection
void SetName(const wxString &aName)
void SetOptionsFromOther(const DRC_CONSTRAINT &aOther)
DRC_RULE * GetParentRule() const
std::map< DRC_CONSTRAINT_T, std::vector< DRC_ENGINE_CONSTRAINT * > * > m_constraintMap
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
void addRule(std::shared_ptr< DRC_RULE > &rule)
PROGRESS_REPORTER * m_progressReporter
void loadRules(const wxFileName &aPath)
Load and parse a rule set from an sexpr text file.
std::vector< DRC_TEST_PROVIDER * > m_testProviders
std::set< int > QueryDistinctConstraints(DRC_CONSTRAINT_T aConstraintId)
DS_PROXY_VIEW_ITEM * m_drawingSheet
NETLIST * m_schematicNetlist
bool KeepRefreshing(bool aWait=false)
bool m_reportAllTrackErrors
bool ReportProgress(double aProgress)
DRC_TEST_PROVIDER * GetTestProvider(const wxString &name) const
bool HasRulesForConstraintType(DRC_CONSTRAINT_T constraintID)
BOARD_DESIGN_SETTINGS * GetDesignSettings() const
void SetMaxProgress(int aSize)
DRC_ENGINE(BOARD *aBoard=nullptr, BOARD_DESIGN_SETTINGS *aSettings=nullptr)
std::vector< int > m_errorLimits
bool IsErrorLimitExceeded(int error_code)
void ProcessAssertions(const BOARD_ITEM *a, std::function< void(const DRC_CONSTRAINT *)> aFailureHandler, REPORTER *aReporter=nullptr)
DRC_VIOLATION_HANDLER m_violationHandler
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
std::vector< std::shared_ptr< DRC_RULE > > m_rules
std::shared_ptr< DRC_RULE > createImplicitRule(const wxString &name)
static bool IsNetADiffPair(BOARD *aBoard, NETINFO_ITEM *aNet, int &aNetP, int &aNetN)
bool IsNetTieExclusion(int aTrackNetCode, PCB_LAYER_ID aTrackLayer, const VECTOR2I &aCollisionPos, BOARD_ITEM *aCollidingItem)
Check if the given collision between a track and another item occurs during the track's entry into a ...
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint)
std::vector< BOARD_ITEM * > GetItemsMatchingCondition(const wxString &aExpression, DRC_CONSTRAINT_T aConstraint=ASSERTION_CONSTRAINT, REPORTER *aReporter=nullptr)
Evaluate a DRC condition against all board items and return matches.
void InitEngine(const wxFileName &aRulePath)
Initialize the DRC engine.
DRC_CONSTRAINT EvalZoneConnection(const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
static int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet, wxString &aBaseDpName)
Check if the given net is a diff pair, returning its polarity and complement if so.
bool ReportPhase(const wxString &aMessage)
BOARD_DESIGN_SETTINGS * m_designSettings
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator={})
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
bool EvaluateFor(const BOARD_ITEM *aItemA, const BOARD_ITEM *aItemB, int aConstraint, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
std::vector< DRC_TEST_PROVIDER * > GetTestProviders() const
static DRC_TEST_PROVIDER_REGISTRY & Instance()
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out DRC_ITEM and posi...
void SetDRCEngine(DRC_ENGINE *engine)
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
KICAD_T Type() const
Returns the type of object.
EDA_ITEM_FLAGS GetFlags() const
A LINE_READER that reads from an open file.
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
LSET is a set of PCB_LAYER_IDs.
static const LSET & FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
static const LSET & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Handle the data for a net.
const wxString & GetNetname() const
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetCompositeNetclasses() const
Gets all composite (multiple assignment / missing defaults) netclasses.
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetNetclasses() const
Gets all netclasses.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
std::optional< int > GetLocalSolderMaskMargin() const
A small class to help profiling.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
double msecs(bool aSinceLast=false)
A pure virtual class used to derive REPORTER objects from.
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
const EDA_IU_SCALE & GetIuScale() const
UNITS_PROVIDER(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
Handle a list of polygons defining a copper zone.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
bool GetDoNotAllowVias() const
bool GetDoNotAllowPads() const
bool GetDoNotAllowTracks() const
int GetMinThickness() const
ZONE_CONNECTION GetPadConnection() const
int GetThermalReliefSpokeWidth() const
bool GetDoNotAllowFootprints() const
bool HasKeepoutParametersSet() const
Accessor to determine if any keepout parameters are set.
bool GetDoNotAllowZoneFills() const
int GetThermalReliefGap() const
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
void drcPrintDebugMessage(int level, const wxString &msg, const char *function, int line)
#define EXTENDED_ERROR_LIMIT
static bool isKeepoutZone(const BOARD_ITEM *aItem, bool aCheckFlags)
@ DRC_DISALLOW_BURIED_VIAS
@ DRC_DISALLOW_BLIND_VIAS
@ DRC_DISALLOW_THROUGH_VIAS
@ DRC_DISALLOW_FOOTPRINTS
@ DRC_DISALLOW_MICRO_VIAS
@ ANNULAR_WIDTH_CONSTRAINT
@ COURTYARD_CLEARANCE_CONSTRAINT
@ VIA_DIAMETER_CONSTRAINT
@ ZONE_CONNECTION_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ MIN_RESOLVED_SPOKES_CONSTRAINT
@ TEXT_THICKNESS_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
@ CONNECTION_WIDTH_CONSTRAINT
@ THERMAL_RELIEF_GAP_CONSTRAINT
@ MAX_UNCOUPLED_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_ABS_MARGIN_CONSTRAINT
@ SOLDER_MASK_EXPANSION_CONSTRAINT
@ PHYSICAL_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_REL_MARGIN_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
constexpr int DRC_DISALLOW_VIAS
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
static FILENAME_RESOLVER * resolver
static const wxChar * traceDrcProfile
Flag to enable DRC profile timing logging.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
PCB_LAYER_ID
A quick note on layer IDs:
KICOMMON_API wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
@ PTH
Plated through hole pad.
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::shared_ptr< DRC_RULE > parentRule
DRC_RULE_CONDITION * condition
DRC_CONSTRAINT constraint
A filename or source description, a problem input line, a line number, a byte offset,...
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I
wxString PrintZoneConnection(ZONE_CONNECTION aConnection)
ZONE_CONNECTION
How pads are covered by copper in zone.
@ THERMAL
Use thermal relief for pads.
@ THT_THERMAL
Thermal relief only for THT pads.
@ FULL
pads are covered by copper