59#define ERROR_LIMIT 199
60#define EXTENDED_ERROR_LIMIT 499
77 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
79 int setLevel = wxAtoi( valueStr );
81 if( level <= setLevel )
82 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
125 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
152 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
155 rule->SetImplicitSource( aImplicitSource );
166 wxString expr, expr2, ncName;
175 rule->AddConstraint( widthConstraint );
179 rule->AddConstraint( connectionConstraint );
183 rule->AddConstraint( drillConstraint );
187 rule->AddConstraint( annulusConstraint );
191 rule->AddConstraint( diameterConstraint );
195 rule->AddConstraint( holeToHoleConstraint );
201 rule->AddConstraint( thermalSpokeCountConstraint );
207 rule->AddConstraint( silkClearanceConstraint );
214 rule->AddConstraint( silkTextHeightConstraint );
221 rule->AddConstraint( silkTextThicknessConstraint );
226 rule->AddConstraint( holeClearanceConstraint );
231 rule->AddConstraint( edgeClearanceConstraint );
236 rule->AddConstraint( courtyardClearanceConstraint );
240 std::shared_ptr<DRC_RULE> uViaRule =
createImplicitRule(
_(
"board setup constraints micro-via" ),
247 uViaRule->AddConstraint( uViaDrillConstraint );
251 uViaRule->AddConstraint( uViaDiameterConstraint );
255 std::shared_ptr<DRC_RULE> barcodeRule =
createImplicitRule(
_(
"barcode visual separation default" ),
259 barcodeRule->AddConstraint( barcodeSeparationConstraint );
264 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
265 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
267 auto makeNetclassRules =
268 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
278 if( nc->HasClearance() )
280 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
281 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
282 nc->GetClearanceParent()->GetHumanReadableName() );
285 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
287 netclassRule->m_ImplicitNetclass = nc->GetName();
288 netclassClearanceRules.push_back( netclassRule );
292 netclassRule->AddConstraint( constraint );
300 if( nc->HasTrackWidth() )
302 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
303 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
304 nc->GetTrackWidthParent()->GetHumanReadableName() );
307 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
309 netclassRule->m_ImplicitNetclass = nc->GetName();
310 netclassClearanceRules.push_back( netclassRule );
315 netclassRule->AddConstraint( constraint );
318 if( nc->HasDiffPairWidth() )
320 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
321 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' diff pair" ),
322 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
325 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
327 netclassRule->m_ImplicitNetclass = nc->GetName();
328 netclassItemSpecificRules.push_back( netclassRule );
332 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
333 netclassRule->AddConstraint( constraint );
336 if( nc->HasDiffPairGap() )
338 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
339 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
340 nc->GetDiffPairGapParent()->GetHumanReadableName() );
343 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
345 netclassRule->m_ImplicitNetclass = nc->GetName();
346 netclassItemSpecificRules.push_back( netclassRule );
351 netclassRule->AddConstraint( constraint );
354 if( nc->HasClearance() && nc->GetDiffPairGap() < nc->GetClearance() )
356 netclassRule = std::make_shared<DRC_RULE>();
357 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' diff pair" ),
358 nc->GetDiffPairGapParent()->GetHumanReadableName() );
361 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
363 netclassRule->m_ImplicitNetclass = nc->GetName();
364 netclassItemSpecificRules.push_back( netclassRule );
367 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
368 netclassRule->AddConstraint( min_clearanceConstraint );
374 if( nc->HasViaDiameter() )
376 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
377 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
378 nc->GetViaDiameterParent()->GetHumanReadableName() );
381 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
383 netclassRule->m_ImplicitNetclass = nc->GetName();
384 netclassItemSpecificRules.push_back( netclassRule );
389 netclassRule->AddConstraint( constraint );
392 if( nc->HasViaDrill() )
394 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
395 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
396 nc->GetViaDrillParent()->GetHumanReadableName() );
399 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
401 netclassRule->m_ImplicitNetclass = nc->GetName();
402 netclassItemSpecificRules.push_back( netclassRule );
407 netclassRule->AddConstraint( constraint );
410 if( nc->HasuViaDiameter() )
412 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
413 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' uvia" ),
414 nc->GetuViaDiameterParent()->GetHumanReadableName() );
417 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
419 netclassRule->m_ImplicitNetclass = nc->GetName();
420 netclassItemSpecificRules.push_back( netclassRule );
424 constraint.
Value().
SetOpt( nc->GetuViaDiameter() );
425 netclassRule->AddConstraint( constraint );
428 if( nc->HasuViaDrill() )
430 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
431 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' uvia" ),
432 nc->GetuViaDrillParent()->GetHumanReadableName() );
435 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
437 netclassRule->m_ImplicitNetclass = nc->GetName();
438 netclassItemSpecificRules.push_back( netclassRule );
443 netclassRule->AddConstraint( constraint );
447 m_board->SynchronizeNetsAndNetClasses(
false );
451 makeNetclassRules( netclass,
false );
454 makeNetclassRules( netclass,
false );
461 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
462 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
464 return lhs->m_Constraints[0].m_Value.Min() < rhs->m_Constraints[0].m_Value.Min();
467 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
470 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
474 auto addTuningSingleRule =
476 const wxString& aNetclassName )
481 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
483 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
486 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s'" ),
495 tuningRule->AddConstraint( constraint );
500 auto addTuningDifferentialRules =
502 const NETCLASS* aNetclass,
const wxString& aNetclassName )
507 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
509 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
512 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
521 tuningRule->AddConstraint( constraint );
525 std::shared_ptr<DRC_RULE> tuningRule2 = std::make_shared<DRC_RULE>();
527 tuningRule2->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
530 expr2 = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
539 tuningRule2->AddConstraint( constraint2 );
544 if( aNetclass->HasClearance() && aLayerEntry.
GetDiffPairGap() < aNetclass->GetClearance() )
546 std::shared_ptr<DRC_RULE> diffPairClearanceRule = std::make_shared<DRC_RULE>();
548 diffPairClearanceRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
551 expr = wxString::Format(
552 wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && AB.isCoupledDiffPair()" ),
558 diffPairClearanceRule->AddConstraint( min_clearanceConstraint );
560 addRule( diffPairClearanceRule );
566 std::shared_ptr<TUNING_PROFILES> tuningParams =
project->GetProjectFile().TuningProfileParameters();
568 auto addNetclassTuningProfileRules =
569 [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules](
NETCLASS* aNetclass )
573 if( aNetclass->HasTuningProfile() && literal )
575 const wxString delayProfileName = aNetclass->GetTuningProfile();
576 const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName );
584 addTuningSingleRule( entry, delayProfileName, *literal );
586 addTuningDifferentialRules( entry, delayProfileName, aNetclass, *literal );
594 addNetclassTuningProfileRules( netclass.get() );
597 addNetclassTuningProfileRules( netclass.get() );
601 auto addKeepoutZoneRule =
611 wxString::Format(
_(
"keepout area of %s" ),
DescribeRef( parentFP->GetReference() ) ),
635 rule->m_ImplicitItemId = zone->
m_Uuid;
636 rule->m_ImplicitItem = zone;
638 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsKeepout('%s')" ),
643 int disallowFlags = 0;
662 rule->AddConstraint( disallowConstraint );
668 addKeepoutZoneRule( zone,
nullptr );
673 for(
ZONE* zone : footprint->Zones() )
676 addKeepoutZoneRule( zone, footprint );
684 if(
m_board && aPath.FileExists() )
686 std::vector<std::shared_ptr<DRC_RULE>> rules;
688 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
693 std::function<bool( wxString* )> resolver =
694 [&]( wxString* token ) ->
bool
699 return m_board->ResolveTextVar( token, 0 );
702 while(
char* line = lineReader.
ReadLine() )
704 wxString str( line );
705 str =
m_board->ConvertCrossReferencesToKIIDs( str );
708 rulesText << str <<
'\n';
718 for( std::shared_ptr<DRC_RULE>& rule : rules )
731 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
735 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
737 condition = rule->m_Condition;
738 condition->
Compile( &error_semaphore );
749 ruleVec =
new std::vector<DRC_ENGINE_CONSTRAINT*>();
753 engineConstraint->
layerTest = rule->m_LayerCondition;
759 && rule->m_ImplicitItem && rule->m_ImplicitItem->Type() ==
PCB_ZONE_T )
766 ruleVec->push_back( engineConstraint );
778 if( c->parentRule && !c->parentRule->IsImplicit() )
787 && c->condition->HasGeometryDependentFunctions() )
804 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
806 provider->SetDRCEngine(
this );
815 if(
DRC_ITEM* drcItem =
static_cast<DRC_ITEM*
>( marker->GetRCItem().get() ) )
816 drcItem->SetViolatingRule(
nullptr );
848 throw original_parse_error;
865 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
867 provider->SetDRCEngine(
this );
876 if(
DRC_ITEM* drcItem =
static_cast<DRC_ITEM*
>( marker->GetRCItem().get() ) )
877 drcItem->SetViolatingRule(
nullptr );
923 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
926 throw original_parse_error;
963 if( !cacheGenerator.
Run() )
967 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
969 int timestamp =
m_board->GetTimeStamp();
974 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
978 if( !provider->RunTests( aUnits ) )
981 providerTimer.
Stop();
982 wxLogTrace(
traceDrcProfile,
"DRC provider '%s' took %0.3f ms", provider->GetName(), providerTimer.
msecs() );
990 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
994#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
1002 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
1007 const PAD*
pad =
nullptr;
1010 pad =
static_cast<const PAD*
>( a );
1012 pad =
static_cast<const PAD*
>( b );
1020 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
1046 const PAD*
pad =
nullptr;
1047 const ZONE* zone =
nullptr;
1048 const FOOTPRINT* parentFootprint =
nullptr;
1058 pad =
static_cast<const PAD*
>( a );
1060 zone =
static_cast<const ZONE*
>( a );
1063 pad =
static_cast<const PAD*
>( b );
1065 zone =
static_cast<const ZONE*
>( b );
1068 parentFootprint =
pad->GetParentFootprint();
1072 constraint.
m_Type = aConstraintType;
1074 auto applyConstraint =
1077 DRC_RULE* rule = c->constraint.GetParentRule();
1082 if( c->constraint.m_Value.HasMin() )
1084 if( c->parentRule && c->parentRule->IsImplicit() )
1093 if( c->constraint.m_Value.HasOpt() )
1099 if( c->constraint.m_Value.HasMax() )
1105 switch( c->constraint.m_Type )
1141 && ( ( ( !ac ) ^ ( !bc ) )
1144 || ( ( footprints[0] == footprints[1] )
1145 && footprints[0] ) )
1147 && !b_is_non_copper )
1154 for(
int ii = 0; ii < 2; ++ii )
1157 if( !footprints[ii] || !alt_items[ii] )
1160 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
1162 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
1164 if( it != netcodes.end() )
1167 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
1168 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
1170 constraint.
SetName(
_(
"net tie" ) );
1180 int override_val = 0;
1181 std::optional<int> overrideA;
1182 std::optional<int> overrideB;
1184 if( ac && !b_is_non_copper )
1187 if( bc && !a_is_non_copper )
1190 if( overrideA.has_value() || overrideB.has_value() )
1194 if( overrideA.has_value() )
1197 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1204 if( overrideB.has_value() )
1207 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1211 if( overrideB > override_val )
1219 if( override_val < m_designSettings->m_MinClearance )
1222 msg =
_(
"board minimum" );
1225 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1231 if( override_val < m_designSettings->m_HoleClearance )
1234 msg =
_(
"board minimum hole" );
1237 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
1256 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
1267 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
1270 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
1273 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
1284 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
1287 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
1290 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
1299 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
1311 std::optional<int>
override;
1315 override =
pad->GetLocalSolderMaskMargin();
1317 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
1321 if( !
override.has_value() &&
pad )
1323 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1325 override = overrideFootprint->GetLocalSolderMaskMargin();
1326 overrideItem = overrideFootprint;
1333 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1343 std::optional<int>
override;
1347 override =
pad->GetLocalSolderPasteMargin();
1349 if( !
override.has_value() &&
pad )
1351 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1353 override = overrideFootprint->GetLocalSolderPasteMargin();
1354 overrideItem = overrideFootprint;
1361 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1371 std::optional<double> overrideRatio;
1375 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1377 if( !overrideRatio.has_value() &&
pad )
1379 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1381 overrideRatio = overrideFootprint->GetLocalSolderPasteMarginRatio();
1382 overrideItem = overrideFootprint;
1389 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1398 auto testAssertion =
1401 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1402 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1404 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1405 REPORT(
_(
"Assertion passed." ) )
1415 std::unordered_map<wxString, bool> conditionCache;
1417 auto reportConstraintHeader =
1422 bool implicit = c->parentRule && c->parentRule->IsImplicit();
1424 switch( c->constraint.m_Type )
1433 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1438 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1443 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1449 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1455 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1461 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1467 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1473 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute clearance: %s." ),
1479 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1485 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1491 REPORT( wxString::Format(
_(
"Checking %s max microvia stack depth: %s." ),
1497 REPORT( wxString::Format(
_(
"Checking %s max hole aspect ratio: %.3f." ),
1499 c->constraint.m_Value.Max() / 1000.0 ) )
1503 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1524 switch( c->constraint.m_Type )
1527 if( c->constraint.m_Value.HasOpt() )
1529 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1533 else if( c->constraint.m_Value.HasMin() )
1535 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1543 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1549 if( c->constraint.m_Value.HasOpt() )
1551 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1555 else if( c->constraint.m_Value.HasMin() )
1557 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1564 if( c->constraint.m_Value.HasOpt() )
1566 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1570 else if( c->constraint.m_Value.HasMin() )
1572 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1582 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1588 if( c->constraint.m_Value.HasOpt() )
1590 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1594 else if( c->constraint.m_Value.HasMin() )
1596 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1604 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1610 REPORT( wxString::Format(
_(
"Checking %s." ),
1616 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1618 c->constraint.m_Value.HasMin()
1620 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1621 c->constraint.m_Value.HasOpt()
1623 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1624 c->constraint.m_Value.HasMax()
1626 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ) ) )
1632 REPORT( wxString::Format(
_(
"Checking %s." ),
EscapeHTML( c->constraint.GetName() ) ) )
1636 auto checkCondition =
1639 bool condMatched =
false;
1648 auto it = conditionCache.find( expr );
1650 if( it != conditionCache.end() )
1652 condMatched = it->second;
1657 conditionCache[expr] = condMatched;
1664 auto processConstraint =
1673 if( a_is_non_copper || b_is_non_copper )
1675 reportConstraintHeader( c );
1676 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1685 if( !netclassName.empty()
1686 && !( acNetclass && acNetclass->
NameEquals( netclassName ) )
1687 && !( bcNetclass && bcNetclass->
NameEquals( netclassName ) ) )
1692 if( !checkCondition( c,
nullptr ) )
1696 reportConstraintHeader( c );
1700 if( a_is_non_copper )
1702 REPORT( wxString::Format(
_(
"%s contains no copper. Constraint ignored." ),
1706 else if( b_is_non_copper )
1708 REPORT( wxString::Format(
_(
"%s contains no copper. Constraint ignored." ),
1719 REPORT(
_(
"Keepout belongs to the footprint under test; constraint ignored." ) )
1733 if(
via->IsMicroVia() )
1735 else if(
via->IsBlindVia() )
1737 else if(
via->IsBuriedVia() )
1760 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1768 default: mask = 0;
break;
1775 REPORT(
_(
"Keepout constraint not met." ) )
1777 REPORT(
_(
"Disallow constraint not met." ) )
1795 if( !( c->
layerTest & itemLayers ).any() )
1799 REPORT(
_(
"Keepout layer(s) not matched." ) )
1803 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1808 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1820 REPORT(
_(
"Constraint layer not matched." ) )
1824 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1829 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1840 REPORT( wxString::Format(
_(
"%s does not have a hole; rule ignored." ),
1849 REPORT(
_(
"Unconditional constraint applied." ) )
1853 REPORT(
_(
"Unconditional rule applied." ) )
1858 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1862 applyConstraint( c );
1885 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1894 condMatched = checkCondition( c, aReporter );
1902 REPORT(
_(
"Constraint applied." ) )
1906 REPORT(
_(
"Rule applied." ) )
1911 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1915 applyConstraint( c );
1919 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1920 :
_(
"Condition not satisfied; rule ignored." ) )
1931 && ( !b || !b_is_non_copper ) )
1957 if( !ncNameA.empty() || !ncNameB.empty() )
1961 if( !ncNameA.empty() )
1967 netclassRule = it->second;
1972 if( !ncNameB.empty() )
1978 netclassRule = it->second;
1998 processConstraint( rule );
2007 REPORT( wxString::Format(
_(
"Resolved minimum clearance: %s." ),
2035 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
2039 a = parentFootprint;
2041 b = parentFootprint;
2045 conditionCache.clear();
2052 processConstraint( rule );
2062 constraint.
SetName(
_(
"board setup" ) );
2069 constraint.
SetName(
_(
"board setup" ) );
2076 constraint.
SetName(
_(
"board setup" ) );
2089 bool needBlankLine =
true;
2098 needBlankLine =
false;
2101 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
2122 needBlankLine =
false;
2125 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
2139 if( !a_is_non_copper && !b_is_non_copper )
2144 needBlankLine =
false;
2147 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
2153 constraint.
SetName(
_(
"board minimum" ) );
2162 if(
pad && parentFootprint )
2169 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
2174 constraint.
SetName(
_(
"footprint" ) );
2185 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
2202 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
2219 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
2284 auto testAssertion =
2287 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
2288 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
2290 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2293 REPORT(
_(
"Assertion passed." ) )
2298 aFailureHandler( &c->constraint );
2302 auto processConstraint =
2306 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
2310 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
2311 EscapeHTML( c->parentRule->m_LayerSource ) ) )
2314 if( !c->condition || c->condition->GetExpression().IsEmpty() )
2316 REPORT(
_(
"Unconditional rule applied." ) )
2321 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
2322 EscapeHTML( c->condition->GetExpression() ) ) )
2324 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2327 REPORT(
_(
"Rule applied." ) )
2332 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
2341 for(
int ii = 0; ii < (int) it->second->size(); ++ii )
2342 processConstraint( it->second->at( ii ) );
2352 assert( error_code >= 0 && error_code <=
DRCE_LAST );
2360 assert( error_code >= 0 && error_code <=
DRCE_LAST );
2367 int aMarkerLayer,
const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
2384 static std::mutex handlerLock;
2385 std::lock_guard<std::mutex> guard( handlerLock );
2391 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
2392 aItem->GetViolatingTest()->GetName(),
2393 aItem->GetErrorMessage(
false ),
2394 aItem->GetErrorCode() );
2396 DRC_RULE* rule = aItem->GetViolatingRule();
2399 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
2403 wxString violatingItemsStr = wxT(
"Violating items: " );
2405 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
2469 bool aUnconditionalOnly )
2478 if( aUnconditionalOnly && c->
condition )
2483 if( current > worst )
2538 std::set<int> distinctMinimums;
2547 return distinctMinimums;
2557 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2561 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
2565 else if( ch ==
'+' )
2567 aComplementNet = wxT(
"-" );
2570 else if( ch ==
'-' )
2572 aComplementNet = wxT(
"+" );
2575 else if( ch ==
'N' )
2577 aComplementNet = wxT(
"P" );
2580 else if ( ch ==
'P' )
2582 aComplementNet = wxT(
"N" );
2591 if( rv != 0 && count >= 1 )
2593 aBaseDpName = aNetName.Left( aNetName.Length() - count );
2594 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
2603 const wxString& refName = aNet->
GetNetname();
2604 wxString
dummy, coupledNetName;
2640 if( parentFootprint && parentFootprint->
IsNetTie() )
2647 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2649 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2661enum class SHOWMATCH_DOMAIN
2668 MASK_EXPANSION_ITEMS,
2681struct SHOWMATCH_DOMAIN_SPEC
2683 SHOWMATCH_DOMAIN primary;
2684 SHOWMATCH_DOMAIN secondary = SHOWMATCH_DOMAIN::ALL_ITEMS;
2685 bool hasSecondary =
false;
2686 bool secondaryUnary =
false;
2690bool isShowMatchSkippable(
const BOARD_ITEM* aItem )
2692 switch( aItem->
Type() )
2698 default:
return false;
2703bool matchesShowMatchDomain(
const BOARD_ITEM* aItem, SHOWMATCH_DOMAIN aDomain )
2705 if( !aItem || isShowMatchSkippable( aItem ) )
2710 case SHOWMATCH_DOMAIN::ALL_ITEMS:
return true;
2714 case SHOWMATCH_DOMAIN::EDGE_ITEMS:
2720 const PAD*
pad =
static_cast<const PAD*
>( aItem );
2728 case SHOWMATCH_DOMAIN::HOLE_ITEMS:
return aItem->
HasHole();
2730 case SHOWMATCH_DOMAIN::MASK_EXPANSION_ITEMS:
2731 switch( aItem->
Type() )
2740 default:
return false;
2745 case SHOWMATCH_DOMAIN::PADS:
return aItem->
Type() ==
PCB_PAD_T;
2751 case SHOWMATCH_DOMAIN::ROUTING_ITEMS:
2752 switch( aItem->
Type() )
2759 default:
return false;
2764 case SHOWMATCH_DOMAIN::SILK_TARGET_ITEMS:
2771 case SHOWMATCH_DOMAIN::TEXT_ITEMS:
2775 case SHOWMATCH_DOMAIN::VIAS:
return aItem->
Type() ==
PCB_VIA_T;
2782SHOWMATCH_DOMAIN_SPEC getShowMatchDomainSpec(
DRC_CONSTRAINT_T aConstraint )
2784 switch( aConstraint )
2801 return { SHOWMATCH_DOMAIN::SILK_ITEMS, SHOWMATCH_DOMAIN::SILK_TARGET_ITEMS,
true,
false };
2835 default:
return { SHOWMATCH_DOMAIN::ALL_ITEMS };
2840std::vector<BOARD_ITEM*> collectShowMatchCandidates(
BOARD* aBoard, SHOWMATCH_DOMAIN aDomain )
2842 std::vector<BOARD_ITEM*> items;
2850 if( matchesShowMatchDomain( aItem, aDomain ) )
2851 items.push_back( aItem );
2859std::vector<PCB_LAYER_ID> getShowMatchLayers(
const BOARD_ITEM* aItem )
2861 std::vector<PCB_LAYER_ID> layers;
2863 switch( aItem->
Type() )
2865 case PCB_PAD_T: layers =
static_cast<const PAD*
>( aItem )->Padstack().UniqueLayers();
break;
2867 case PCB_VIA_T: layers =
static_cast<const PCB_VIA*
>( aItem )->Padstack().UniqueLayers();
break;
2871 layers.push_back( layer );
2876 if( layers.empty() )
2886 bool testedLayer =
false;
2888 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItem ) )
2913std::vector<PCB_LAYER_ID> getShowMatchPairLayers(
const DRC_RULE& aRule,
const BOARD_ITEM* aItemA,
2916 std::vector<PCB_LAYER_ID> layers;
2917 std::set<int> seenLayers;
2925 if( seenLayers.insert(
static_cast<int>( aLayer ) ).second )
2926 layers.push_back( aLayer );
2929 switch( aConstraint )
2932 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemA ) )
2940 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemA ) )
2943 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemB ) )
2949 if( layers.empty() )
2959 for(
PCB_LAYER_ID layer : getShowMatchPairLayers( aRule, aItemA, aItemB, aConstraint ) )
2977 if(
name == prov->GetName() )
2989 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine enter: expr='%s', constraint=%d" ),
2990 aExpression, (
int) aConstraint );
2992 std::vector<BOARD_ITEM*> matches;
3001 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine: compile failed" ) );
3008 if( std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_board->GetConnectivity() )
3010 if( std::shared_ptr<FROM_TO_CACHE> ftCache = connectivity->GetFromToCache() )
3014 size_t totalItems = 0;
3015 size_t skippedItems = 0;
3016 size_t noLayerItems = 0;
3017 size_t checkedItems = 0;
3019 const auto applyConditionToItemFunc =
3025 switch( aItem->
Type() )
3040 if( itemLayers.none() )
3047 bool matched =
false;
3051 if( condition.
EvaluateFor( aItem,
nullptr,
static_cast<int>( aConstraint ), layer,
3054 matches.push_back( aItem );
3055 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
3056 wxS(
"[ShowMatches] engine: match type=%d kiid=%s layer=%d" ),
3064 if( !matched && matches.size() == 0 && checkedItems <= 5 )
3066 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
3067 wxS(
"[ShowMatches] engine: no-match sample type=%d kiid=%s layers=%s" ),
3074 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
3075 wxS(
"[ShowMatches] engine stats: total=%zu skipped=%zu noLayer=%zu checked=%zu" ),
3076 totalItems, skippedItems, noLayerItems, checkedItems );
3078 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine exit: total=%zu" ), matches.size() );
3085 std::vector<BOARD_ITEM*> matches;
3090 const bool requiresPairwise = aRule->m_Condition && aRule->m_Condition->RequiresPairItems();
3091 std::set<BOARD_ITEM*> matchedItems;
3093 if( std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_board->GetConnectivity() )
3095 if( std::shared_ptr<FROM_TO_CACHE> ftCache = connectivity->GetFromToCache() )
3104 SHOWMATCH_DOMAIN_SPEC domainSpec = getShowMatchDomainSpec( constraint.
m_Type );
3105 std::vector<BOARD_ITEM*> primaryItems = collectShowMatchCandidates(
m_board, domainSpec.primary );
3106 std::vector<BOARD_ITEM*> secondaryItems;
3108 if( domainSpec.hasSecondary )
3109 secondaryItems = collectShowMatchCandidates(
m_board, domainSpec.secondary );
3111 if( requiresPairwise )
3113 if( secondaryItems.empty() )
3115 for(
size_t ii = 0; ii < primaryItems.size(); ++ii )
3119 for(
size_t jj = ii + 1; jj < primaryItems.size(); ++jj )
3123 if( ruleMatchesPair( *aRule, itemA, itemB, constraint.
m_Type,
3126 matchedItems.insert( itemA );
3127 matchedItems.insert( itemB );
3138 if( itemA == itemB )
3141 if( ruleMatchesPair( *aRule, itemA, itemB, constraint.
m_Type,
3144 matchedItems.insert( itemA );
3145 matchedItems.insert( itemB );
3155 if( ruleMatchesUnary( *aRule, item, constraint.
m_Type, aReporter ? aReporter :
m_logReporter ) )
3157 matchedItems.insert( item );
3161 if( domainSpec.hasSecondary && domainSpec.secondaryUnary )
3165 if( ruleMatchesUnary( *aRule, item, constraint.
m_Type, aReporter ? aReporter :
m_logReporter ) )
3167 matchedItems.insert( item );
3174 matches.assign( matchedItems.begin(), matchedItems.end() );
3204 const PAD*
pad =
static_cast<const PAD*
>( aItem );
3219 *aSource = constraint.
GetName();
3249 std::erase_if(
m_ownClearanceCache, [&aUuid](
const auto& entry ) {
return entry.first.m_uuid == aUuid; } );
3271 using CLEARANCE_MAP = std::unordered_map<DRC_OWN_CLEARANCE_CACHE_KEY, int>;
3275 std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>> itemsToProcess;
3276 size_t estimatedPads = 0;
3279 estimatedPads += footprint->Pads().size();
3281 itemsToProcess.reserve(
m_board->Tracks().size() + estimatedPads * 2 );
3288 itemsToProcess.emplace_back( track, layer );
3292 itemsToProcess.emplace_back( track, track->GetLayer() );
3298 for(
PAD*
pad : footprint->Pads() )
3301 itemsToProcess.emplace_back(
pad, layer );
3305 if( itemsToProcess.empty() )
3316 [
this](
size_t aStart,
size_t aEnd,
const std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>>& aItems )
3319 CLEARANCE_MAP localCache;
3321 for(
size_t i = aStart; i < aEnd; ++i )
3330 const PAD*
pad =
static_cast<const PAD*
>( item );
3349 auto results =
tp.submit_blocks( 0, itemsToProcess.size(),
3350 [&](
size_t aStart,
size_t aEnd ) -> CLEARANCE_MAP
3352 return processItems( aStart, aEnd, itemsToProcess );
3359 std::vector<CLEARANCE_MAP> collectedResults;
3360 collectedResults.reserve( results.size() );
3362 for(
size_t i = 0; i < results.size(); ++i )
3364 if( results[i].valid() )
3365 collectedResults.push_back( results[i].get() );
3372 for(
const auto& localCache : collectedResults )
constexpr EDA_IU_SCALE pcbIUScale
#define MAXIMUM_CLEARANCE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
std::string FmtHex() const
Return a hex string showing contents of this set.
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 NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
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
std::map< int, SEVERITY > m_DRCSeverities
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 bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
virtual bool IsOnCopperLayer() const
virtual bool HasHole() const
Information pertinent to a Pcbnew printed circuit board.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const override
Invoke a function on all children.
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Represents a single line in a time domain profile track propagation setup.
int GetDiffPairGap() const
PCB_LAYER_ID GetSignalLayer() const
virtual bool Run() override
Discard the board's run-time DRC caches and regenerate them from scratch.
DRC_RULE * GetOptRule() const
DRC_RULE * GetMinRule() const
void SetParentRule(DRC_RULE *aParentRule)
Attribute the constraint, including each min, opt and max value it has, to aParentRule.
MINOPTMAX< int > & Value()
const MINOPTMAX< int > & GetValue() const
ZONE_CONNECTION m_ZoneConnection
void SetName(const wxString &aName)
void SetOptionsFromOther(const DRC_CONSTRAINT &aOther)
DRC_RULE * GetMaxRule() const
void SetValueRules(DRC_RULE *aMinRule, DRC_RULE *aOptRule, DRC_RULE *aMaxRule)
DRC_RULE * GetParentRule() const
std::map< DRC_CONSTRAINT_T, std::vector< DRC_ENGINE_CONSTRAINT * > * > m_constraintMap
DRC_CLEARANCE_BATCH EvalClearanceBatch(const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer)
Evaluate all clearance-related constraints in a single batch call.
std::shared_ptr< DRC_RULE > createImplicitRule(const wxString &name, DRC_IMPLICIT_SOURCE aImplicitSource)
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
std::unordered_map< DRC_OWN_CLEARANCE_CACHE_KEY, int > m_ownClearanceCache
bool m_hasDiffPairClearanceOverrides
void addRule(std::shared_ptr< DRC_RULE > &rule)
PROGRESS_REPORTER * m_progressReporter
void ClearClearanceCache()
Clear the entire clearance cache.
void loadRules(const wxFileName &aPath)
Load and parse a rule set from an sexpr text file.
std::vector< DRC_TEST_PROVIDER * > m_testProviders
std::map< DRC_CONSTRAINT_T, std::vector< DRC_ENGINE_CONSTRAINT * > > m_explicitConstraints
int GetErrorLimit(int error_code)
Return the number of violations of error_code that may still be reported.
std::unordered_map< wxString, DRC_RULE * > m_netclassClearances
std::set< int > QueryDistinctConstraints(DRC_CONSTRAINT_T aConstraintId)
bool m_hasGeometryDependentRules
DS_PROXY_VIEW_ITEM * m_drawingSheet
NETLIST * m_schematicNetlist
std::shared_mutex m_clearanceCacheMutex
bool KeepRefreshing(bool aWait=false)
std::vector< BOARD_ITEM * > GetItemsMatchingRule(const std::shared_ptr< DRC_RULE > &aRule, REPORTER *aReporter=nullptr)
bool HasUserDefinedConstraint(DRC_CONSTRAINT_T aConstraintId)
bool HasConditionalConstraint(DRC_CONSTRAINT_T aConstraintId)
int GetCachedOwnClearance(const BOARD_ITEM *aItem, PCB_LAYER_ID aLayer, wxString *aSource=nullptr)
Get the cached own clearance for an item on a specific layer.
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)
bool m_hasExplicitClearanceRules
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
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint, bool aUnconditionalOnly=false)
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 ...
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)
static bool IsNetADiffPair(BOARD *aBoard, const NETINFO_ITEM *aNet, int &aNetP, int &aNetN)
void InitializeClearanceCache()
Initialize the clearance cache for all items on the board.
void InvalidateClearanceCache(const KIID &aUuid)
Invalidate the clearance cache for a specific item.
BOARD_DESIGN_SETTINGS * m_designSettings
bool HasUserDefinedPhysicalConstraint()
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator={})
std::mutex m_errorLimitsMutex
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
wxString GetExpression() const
bool EvaluateFor(const BOARD_ITEM *aItemA, const BOARD_ITEM *aItemB, int aConstraint, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
DRC_RULE_CONDITION * m_Condition
std::vector< DRC_CONSTRAINT > m_Constraints
wxString m_ImplicitNetclass
Netclass named by an implicit netclass rule's condition.
DRC_IMPLICIT_SOURCE GetImplicitSource() const
std::vector< DRC_TEST_PROVIDER * > GetShowMatchesProviders() const
static DRC_SHOWMATCHES_PROVIDER_REGISTRY & Instance()
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 const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
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.
wxString AsString() const
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 & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
A collection of nets and the parameters used to route or test these nets.
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
bool NameEquals(const wxString &aName) const
Compares a name with GetName() without constructing the aggregate name.
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() const
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)
Container for project specific data.
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
wxString MessageTextFromUnscaledValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) 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
const BOX2I GetBoundingBox() const override
bool GetDoNotAllowTracks() const
const wxString & GetZoneName() const
int GetMinThickness() const
ZONE_CONNECTION GetPadConnection() const
int GetThermalReliefSpokeWidth() const
bool GetDoNotAllowFootprints() const
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
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, RESOLUTION_CONTEXT aContext)
wxString DescribeRef(const wxString &aRef)
Returns a user-visible HTML string describing a footprint reference designator.
@ 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
@ NET_CHAIN_LENGTH_CONSTRAINT
@ SOLDER_MASK_SLIVER_CONSTRAINT
@ NET_CHAIN_STUB_LENGTH_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ MIN_RESOLVED_SPOKES_CONSTRAINT
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
@ HOLE_ASPECT_RATIO_CONSTRAINT
@ TEXT_THICKNESS_CONSTRAINT
@ NET_CHAIN_RETURN_PATH_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
@ CONNECTION_WIDTH_CONSTRAINT
@ THERMAL_RELIEF_GAP_CONSTRAINT
@ MAX_UNCOUPLED_CONSTRAINT
@ MICROVIA_STACK_DEPTH_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
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)
@ DRCE_TUNING_PROFILE_IMPLICIT_RULES
bool IsComponentClassSelector(const wxString &aToken)
${Class:X} inside a DRC rule is a component-class selector consumed by testFootprintSelector(),...
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
static const wxChar * traceDrcProfile
Flag to enable DRC profile timing logging.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
bool IsPcbLayer(int aLayer)
Test whether a layer is a valid layer for Pcbnew.
PCB_LAYER_ID
A quick note on layer IDs:
std::optional< wxString > EscapeStringLiteral(const wxString &aText)
Escape text for use between the quotes of an expression string.
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ PTH
Plated through hole pad.
std::deque< FOOTPRINT * > FOOTPRINTS
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
Batch result for clearance-related constraints to reduce per-query overhead during PNS routing.
ZONE * implicitKeepoutZone
std::shared_ptr< DRC_RULE > parentRule
DRC_RULE_CONDITION * condition
DRC_CONSTRAINT constraint
Cache key for own clearance lookups, combining item UUID and layer.
A filename or source description, a problem input line, a line number, a byte offset,...
Represents a single line in the tuning profile configuration grid.
std::vector< DELAY_PROFILE_TRACK_PROPAGATION_ENTRY > m_TrackPropagationEntries
static const long long MM
wxString result
Test unit parsing edge cases and error handling.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
@ PCB_CONSTRAINT_T
a geometric constraint between board items
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ 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_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
@ 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_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
@ PCB_DRILL_CHART_T
class PCB_DRILL_CHART, a live drill chart derived from PCB_TABLE
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