57#define ERROR_LIMIT 199
58#define EXTENDED_ERROR_LIMIT 499
75 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
77 int setLevel = wxAtoi( valueStr );
79 if( level <= setLevel )
80 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
123 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
150 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
153 rule->SetImplicitSource( aImplicitSource );
164 wxString expr, expr2, ncName;
173 rule->AddConstraint( widthConstraint );
177 rule->AddConstraint( connectionConstraint );
181 rule->AddConstraint( drillConstraint );
185 rule->AddConstraint( annulusConstraint );
189 rule->AddConstraint( diameterConstraint );
193 rule->AddConstraint( holeToHoleConstraint );
199 rule->AddConstraint( thermalSpokeCountConstraint );
205 rule->AddConstraint( silkClearanceConstraint );
212 rule->AddConstraint( silkTextHeightConstraint );
219 rule->AddConstraint( silkTextThicknessConstraint );
224 rule->AddConstraint( holeClearanceConstraint );
229 rule->AddConstraint( edgeClearanceConstraint );
234 rule->AddConstraint( courtyardClearanceConstraint );
238 std::shared_ptr<DRC_RULE> uViaRule =
createImplicitRule(
_(
"board setup constraints micro-via" ),
245 uViaRule->AddConstraint( uViaDrillConstraint );
249 uViaRule->AddConstraint( uViaDiameterConstraint );
253 std::shared_ptr<DRC_RULE> barcodeRule =
createImplicitRule(
_(
"barcode visual separation default" ),
257 barcodeRule->AddConstraint( barcodeSeparationConstraint );
262 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
263 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
265 auto makeNetclassRules =
266 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
268 ncName = nc->GetName();
269 ncName.Replace(
"'",
"\\'" );
271 if( nc->HasClearance() )
273 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
274 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
275 nc->GetClearanceParent()->GetHumanReadableName() );
278 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
280 netclassRule->m_ImplicitNetclass = nc->GetName();
281 netclassClearanceRules.push_back( netclassRule );
285 netclassRule->AddConstraint( constraint );
293 if( nc->HasTrackWidth() )
295 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
296 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
297 nc->GetTrackWidthParent()->GetHumanReadableName() );
300 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
302 netclassRule->m_ImplicitNetclass = nc->GetName();
303 netclassClearanceRules.push_back( netclassRule );
308 netclassRule->AddConstraint( constraint );
311 if( nc->HasDiffPairWidth() )
313 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
314 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' diff pair" ),
315 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
318 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
320 netclassRule->m_ImplicitNetclass = nc->GetName();
321 netclassItemSpecificRules.push_back( netclassRule );
325 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
326 netclassRule->AddConstraint( constraint );
329 if( nc->HasDiffPairGap() )
331 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
332 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
333 nc->GetDiffPairGapParent()->GetHumanReadableName() );
336 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
338 netclassRule->m_ImplicitNetclass = nc->GetName();
339 netclassItemSpecificRules.push_back( netclassRule );
344 netclassRule->AddConstraint( constraint );
347 if( nc->HasClearance() && nc->GetDiffPairGap() < nc->GetClearance() )
349 netclassRule = std::make_shared<DRC_RULE>();
350 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' diff pair" ),
351 nc->GetDiffPairGapParent()->GetHumanReadableName() );
354 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
356 netclassRule->m_ImplicitNetclass = nc->GetName();
357 netclassItemSpecificRules.push_back( netclassRule );
360 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
361 netclassRule->AddConstraint( min_clearanceConstraint );
367 if( nc->HasViaDiameter() )
369 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
370 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
371 nc->GetViaDiameterParent()->GetHumanReadableName() );
374 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
376 netclassRule->m_ImplicitNetclass = nc->GetName();
377 netclassItemSpecificRules.push_back( netclassRule );
382 netclassRule->AddConstraint( constraint );
385 if( nc->HasViaDrill() )
387 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
388 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
389 nc->GetViaDrillParent()->GetHumanReadableName() );
392 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
394 netclassRule->m_ImplicitNetclass = nc->GetName();
395 netclassItemSpecificRules.push_back( netclassRule );
400 netclassRule->AddConstraint( constraint );
403 if( nc->HasuViaDiameter() )
405 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
406 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' uvia" ),
407 nc->GetuViaDiameterParent()->GetHumanReadableName() );
410 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
412 netclassRule->m_ImplicitNetclass = nc->GetName();
413 netclassItemSpecificRules.push_back( netclassRule );
417 constraint.
Value().
SetOpt( nc->GetuViaDiameter() );
418 netclassRule->AddConstraint( constraint );
421 if( nc->HasuViaDrill() )
423 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
424 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' uvia" ),
425 nc->GetuViaDrillParent()->GetHumanReadableName() );
428 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
430 netclassRule->m_ImplicitNetclass = nc->GetName();
431 netclassItemSpecificRules.push_back( netclassRule );
436 netclassRule->AddConstraint( constraint );
440 m_board->SynchronizeNetsAndNetClasses(
false );
444 makeNetclassRules( netclass,
false );
447 makeNetclassRules( netclass,
false );
454 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
455 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
457 return lhs->m_Constraints[0].m_Value.Min() < rhs->m_Constraints[0].m_Value.Min();
460 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
463 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
467 auto addTuningSingleRule =
469 const wxString& aNetclassName )
474 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
476 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
479 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s'" ),
488 tuningRule->AddConstraint( constraint );
493 auto addTuningDifferentialRules =
500 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
502 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
505 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
506 aNetclass->GetName(),
514 tuningRule->AddConstraint( constraint );
518 std::shared_ptr<DRC_RULE> tuningRule2 = std::make_shared<DRC_RULE>();
520 tuningRule2->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
523 expr2 = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
524 aNetclass->GetName(),
532 tuningRule2->AddConstraint( constraint2 );
537 if( aNetclass->HasClearance() && aLayerEntry.
GetDiffPairGap() < aNetclass->GetClearance() )
539 std::shared_ptr<DRC_RULE> diffPairClearanceRule = std::make_shared<DRC_RULE>();
541 diffPairClearanceRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
544 expr = wxString::Format(
545 wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && AB.isCoupledDiffPair()" ),
551 diffPairClearanceRule->AddConstraint( min_clearanceConstraint );
553 addRule( diffPairClearanceRule );
559 std::shared_ptr<TUNING_PROFILES> tuningParams =
project->GetProjectFile().TuningProfileParameters();
561 auto addNetclassTuningProfileRules =
562 [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules](
NETCLASS* aNetclass )
564 if( aNetclass->HasTuningProfile() )
566 const wxString delayProfileName = aNetclass->GetTuningProfile();
567 const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName );
575 addTuningSingleRule( entry, delayProfileName, aNetclass->GetName() );
577 addTuningDifferentialRules( entry, delayProfileName, aNetclass );
585 addNetclassTuningProfileRules( netclass.get() );
588 addNetclassTuningProfileRules( netclass.get() );
592 auto addKeepoutZoneRule =
602 wxString::Format(
_(
"keepout area of %s" ),
DescribeRef( parentFP->GetReference() ) ),
626 rule->m_ImplicitItemId = zone->
m_Uuid;
627 rule->m_ImplicitItem = zone;
629 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsKeepout('%s')" ),
634 int disallowFlags = 0;
653 rule->AddConstraint( disallowConstraint );
659 addKeepoutZoneRule( zone,
nullptr );
664 for(
ZONE* zone : footprint->Zones() )
667 addKeepoutZoneRule( zone, footprint );
675 if(
m_board && aPath.FileExists() )
677 std::vector<std::shared_ptr<DRC_RULE>> rules;
679 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
684 std::function<bool( wxString* )> resolver =
685 [&]( wxString* token ) ->
bool
690 return m_board->ResolveTextVar( token, 0 );
693 while(
char* line = lineReader.
ReadLine() )
695 wxString str( line );
696 str =
m_board->ConvertCrossReferencesToKIIDs( str );
699 rulesText << str <<
'\n';
709 for( std::shared_ptr<DRC_RULE>& rule : rules )
722 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
726 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
728 condition = rule->m_Condition;
729 condition->
Compile( &error_semaphore );
740 ruleVec =
new std::vector<DRC_ENGINE_CONSTRAINT*>();
744 engineConstraint->
layerTest = rule->m_LayerCondition;
750 && rule->m_ImplicitItem && rule->m_ImplicitItem->Type() ==
PCB_ZONE_T )
757 ruleVec->push_back( engineConstraint );
769 if( c->parentRule && !c->parentRule->IsImplicit() )
778 && c->condition->HasGeometryDependentFunctions() )
795 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
797 provider->SetDRCEngine(
this );
806 if(
DRC_ITEM* drcItem =
static_cast<DRC_ITEM*
>( marker->GetRCItem().get() ) )
807 drcItem->SetViolatingRule(
nullptr );
839 throw original_parse_error;
856 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
858 provider->SetDRCEngine(
this );
867 if(
DRC_ITEM* drcItem =
static_cast<DRC_ITEM*
>( marker->GetRCItem().get() ) )
868 drcItem->SetViolatingRule(
nullptr );
914 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
917 throw original_parse_error;
954 if( !cacheGenerator.
Run() )
958 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
960 int timestamp =
m_board->GetTimeStamp();
965 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
969 if( !provider->RunTests( aUnits ) )
972 providerTimer.
Stop();
973 wxLogTrace(
traceDrcProfile,
"DRC provider '%s' took %0.3f ms", provider->GetName(), providerTimer.
msecs() );
981 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
985#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
993 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
1001 pad =
static_cast<const PAD*
>( a );
1003 pad =
static_cast<const PAD*
>( b );
1011 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
1037 const PAD*
pad =
nullptr;
1038 const ZONE* zone =
nullptr;
1039 const FOOTPRINT* parentFootprint =
nullptr;
1049 pad =
static_cast<const PAD*
>( a );
1051 zone =
static_cast<const ZONE*
>( a );
1054 pad =
static_cast<const PAD*
>( b );
1056 zone =
static_cast<const ZONE*
>( b );
1059 parentFootprint =
pad->GetParentFootprint();
1063 constraint.
m_Type = aConstraintType;
1065 auto applyConstraint =
1068 DRC_RULE* rule = c->constraint.GetParentRule();
1073 if( c->constraint.m_Value.HasMin() )
1075 if( c->parentRule && c->parentRule->IsImplicit() )
1084 if( c->constraint.m_Value.HasOpt() )
1090 if( c->constraint.m_Value.HasMax() )
1096 switch( c->constraint.m_Type )
1132 && ( ( ( !ac ) ^ ( !bc ) )
1135 || ( ( footprints[0] == footprints[1] )
1136 && footprints[0] ) )
1138 && !b_is_non_copper )
1145 for(
int ii = 0; ii < 2; ++ii )
1148 if( !footprints[ii] || !alt_items[ii] )
1151 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
1153 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
1155 if( it != netcodes.end() )
1158 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
1159 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
1161 constraint.
SetName(
_(
"net tie" ) );
1171 int override_val = 0;
1172 std::optional<int> overrideA;
1173 std::optional<int> overrideB;
1175 if( ac && !b_is_non_copper )
1178 if( bc && !a_is_non_copper )
1181 if( overrideA.has_value() || overrideB.has_value() )
1185 if( overrideA.has_value() )
1188 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1195 if( overrideB.has_value() )
1198 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1202 if( overrideB > override_val )
1210 if( override_val < m_designSettings->m_MinClearance )
1213 msg =
_(
"board minimum" );
1216 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1222 if( override_val < m_designSettings->m_HoleClearance )
1225 msg =
_(
"board minimum hole" );
1228 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
1247 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
1258 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
1261 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
1264 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
1275 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
1278 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
1281 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
1290 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
1302 std::optional<int>
override;
1306 override =
pad->GetLocalSolderMaskMargin();
1308 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
1312 if( !
override.has_value() &&
pad )
1314 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1316 override = overrideFootprint->GetLocalSolderMaskMargin();
1317 overrideItem = overrideFootprint;
1324 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1334 std::optional<int>
override;
1338 override =
pad->GetLocalSolderPasteMargin();
1340 if( !
override.has_value() &&
pad )
1342 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1344 override = overrideFootprint->GetLocalSolderPasteMargin();
1345 overrideItem = overrideFootprint;
1352 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1362 std::optional<double> overrideRatio;
1366 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1368 if( !overrideRatio.has_value() &&
pad )
1370 if(
FOOTPRINT* overrideFootprint =
pad->GetParentFootprint() )
1372 overrideRatio = overrideFootprint->GetLocalSolderPasteMarginRatio();
1373 overrideItem = overrideFootprint;
1380 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1389 auto testAssertion =
1392 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1393 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1395 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1396 REPORT(
_(
"Assertion passed." ) )
1406 std::unordered_map<wxString, bool> conditionCache;
1408 auto reportConstraintHeader =
1413 bool implicit = c->parentRule && c->parentRule->IsImplicit();
1415 switch( c->constraint.m_Type )
1424 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1429 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1434 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1440 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1446 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1452 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1458 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1464 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute clearance: %s." ),
1470 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1476 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1482 REPORT( wxString::Format(
_(
"Checking %s max microvia stack depth: %s." ),
1488 REPORT( wxString::Format(
_(
"Checking %s max microvia aspect ratio: %.3f." ),
1490 c->constraint.m_Value.Max() / 1000.0 ) )
1494 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1515 switch( c->constraint.m_Type )
1518 if( c->constraint.m_Value.HasOpt() )
1520 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1524 else if( c->constraint.m_Value.HasMin() )
1526 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1534 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1540 if( c->constraint.m_Value.HasOpt() )
1542 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1546 else if( c->constraint.m_Value.HasMin() )
1548 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1555 if( c->constraint.m_Value.HasOpt() )
1557 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1561 else if( c->constraint.m_Value.HasMin() )
1563 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1573 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1579 if( c->constraint.m_Value.HasOpt() )
1581 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1585 else if( c->constraint.m_Value.HasMin() )
1587 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1595 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1601 REPORT( wxString::Format(
_(
"Checking %s." ),
1607 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1609 c->constraint.m_Value.HasMin()
1611 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1612 c->constraint.m_Value.HasOpt()
1614 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1615 c->constraint.m_Value.HasMax()
1617 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ) ) )
1623 REPORT( wxString::Format(
_(
"Checking %s." ),
EscapeHTML( c->constraint.GetName() ) ) )
1627 auto checkCondition =
1630 bool condMatched =
false;
1639 auto it = conditionCache.find( expr );
1641 if( it != conditionCache.end() )
1643 condMatched = it->second;
1648 conditionCache[expr] = condMatched;
1655 auto processConstraint =
1664 if( a_is_non_copper || b_is_non_copper )
1666 reportConstraintHeader( c );
1667 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1676 if( !netclassName.empty()
1677 && !( acNetclass && acNetclass->
NameEquals( netclassName ) )
1678 && !( bcNetclass && bcNetclass->
NameEquals( netclassName ) ) )
1683 if( !checkCondition( c,
nullptr ) )
1687 reportConstraintHeader( c );
1691 if( a_is_non_copper )
1693 REPORT( wxString::Format(
_(
"%s contains no copper. Constraint ignored." ),
1697 else if( b_is_non_copper )
1699 REPORT( wxString::Format(
_(
"%s contains no copper. Constraint ignored." ),
1710 REPORT(
_(
"Keepout belongs to the footprint under test; constraint ignored." ) )
1724 if(
via->IsMicroVia() )
1726 else if(
via->IsBlindVia() )
1728 else if(
via->IsBuriedVia() )
1751 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1759 default: mask = 0;
break;
1766 REPORT(
_(
"Keepout constraint not met." ) )
1768 REPORT(
_(
"Disallow constraint not met." ) )
1786 if( !( c->
layerTest & itemLayers ).any() )
1790 REPORT(
_(
"Keepout layer(s) not matched." ) )
1794 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1799 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1811 REPORT(
_(
"Constraint layer not matched." ) )
1815 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1820 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1831 REPORT( wxString::Format(
_(
"%s does not have a hole; rule ignored." ),
1840 REPORT(
_(
"Unconditional constraint applied." ) )
1844 REPORT(
_(
"Unconditional rule applied." ) )
1849 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1853 applyConstraint( c );
1876 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1885 condMatched = checkCondition( c, aReporter );
1893 REPORT(
_(
"Constraint applied." ) )
1897 REPORT(
_(
"Rule applied." ) )
1902 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1906 applyConstraint( c );
1910 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1911 :
_(
"Condition not satisfied; rule ignored." ) )
1922 && ( !b || !b_is_non_copper ) )
1948 if( !ncNameA.empty() || !ncNameB.empty() )
1952 if( !ncNameA.empty() )
1958 netclassRule = it->second;
1963 if( !ncNameB.empty() )
1969 netclassRule = it->second;
1989 processConstraint( rule );
1998 REPORT( wxString::Format(
_(
"Resolved minimum clearance: %s." ),
2026 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
2030 a = parentFootprint;
2032 b = parentFootprint;
2036 conditionCache.clear();
2043 processConstraint( rule );
2053 constraint.
SetName(
_(
"board setup" ) );
2060 constraint.
SetName(
_(
"board setup" ) );
2067 constraint.
SetName(
_(
"board setup" ) );
2080 bool needBlankLine =
true;
2089 needBlankLine =
false;
2092 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
2113 needBlankLine =
false;
2116 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
2130 if( !a_is_non_copper && !b_is_non_copper )
2135 needBlankLine =
false;
2138 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
2144 constraint.
SetName(
_(
"board minimum" ) );
2153 if(
pad && parentFootprint )
2160 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
2165 constraint.
SetName(
_(
"footprint" ) );
2176 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
2193 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
2210 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
2275 auto testAssertion =
2278 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
2279 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
2281 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2284 REPORT(
_(
"Assertion passed." ) )
2289 aFailureHandler( &c->constraint );
2293 auto processConstraint =
2297 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
2301 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
2302 EscapeHTML( c->parentRule->m_LayerSource ) ) )
2305 if( !c->condition || c->condition->GetExpression().IsEmpty() )
2307 REPORT(
_(
"Unconditional rule applied." ) )
2312 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
2313 EscapeHTML( c->condition->GetExpression() ) ) )
2315 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
2318 REPORT(
_(
"Rule applied." ) )
2323 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
2332 for(
int ii = 0; ii < (int) it->second->size(); ++ii )
2333 processConstraint( it->second->at( ii ) );
2343 assert( error_code >= 0 && error_code <=
DRCE_LAST );
2351 assert( error_code >= 0 && error_code <=
DRCE_LAST );
2358 int aMarkerLayer,
const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
2375 static std::mutex handlerLock;
2376 std::lock_guard<std::mutex> guard( handlerLock );
2382 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
2383 aItem->GetViolatingTest()->GetName(),
2384 aItem->GetErrorMessage(
false ),
2385 aItem->GetErrorCode() );
2387 DRC_RULE* rule = aItem->GetViolatingRule();
2390 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
2394 wxString violatingItemsStr = wxT(
"Violating items: " );
2396 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
2460 bool aUnconditionalOnly )
2469 if( aUnconditionalOnly && c->
condition )
2474 if( current > worst )
2512 std::set<int> distinctMinimums;
2521 return distinctMinimums;
2531 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2535 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
2539 else if( ch ==
'+' )
2541 aComplementNet = wxT(
"-" );
2544 else if( ch ==
'-' )
2546 aComplementNet = wxT(
"+" );
2549 else if( ch ==
'N' )
2551 aComplementNet = wxT(
"P" );
2554 else if ( ch ==
'P' )
2556 aComplementNet = wxT(
"N" );
2565 if( rv != 0 && count >= 1 )
2567 aBaseDpName = aNetName.Left( aNetName.Length() - count );
2568 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
2577 const wxString& refName = aNet->
GetNetname();
2578 wxString
dummy, coupledNetName;
2614 if( parentFootprint && parentFootprint->
IsNetTie() )
2621 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2623 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2635enum class SHOWMATCH_DOMAIN
2642 MASK_EXPANSION_ITEMS,
2655struct SHOWMATCH_DOMAIN_SPEC
2657 SHOWMATCH_DOMAIN primary;
2658 SHOWMATCH_DOMAIN secondary = SHOWMATCH_DOMAIN::ALL_ITEMS;
2659 bool hasSecondary =
false;
2660 bool secondaryUnary =
false;
2664bool isShowMatchSkippable(
const BOARD_ITEM* aItem )
2666 switch( aItem->
Type() )
2672 default:
return false;
2677bool matchesShowMatchDomain(
const BOARD_ITEM* aItem, SHOWMATCH_DOMAIN aDomain )
2679 if( !aItem || isShowMatchSkippable( aItem ) )
2684 case SHOWMATCH_DOMAIN::ALL_ITEMS:
return true;
2688 case SHOWMATCH_DOMAIN::EDGE_ITEMS:
2694 const PAD*
pad =
static_cast<const PAD*
>( aItem );
2702 case SHOWMATCH_DOMAIN::HOLE_ITEMS:
return aItem->
HasHole();
2704 case SHOWMATCH_DOMAIN::MASK_EXPANSION_ITEMS:
2705 switch( aItem->
Type() )
2714 default:
return false;
2719 case SHOWMATCH_DOMAIN::PADS:
return aItem->
Type() ==
PCB_PAD_T;
2725 case SHOWMATCH_DOMAIN::ROUTING_ITEMS:
2726 switch( aItem->
Type() )
2733 default:
return false;
2738 case SHOWMATCH_DOMAIN::SILK_TARGET_ITEMS:
2745 case SHOWMATCH_DOMAIN::TEXT_ITEMS:
2749 case SHOWMATCH_DOMAIN::VIAS:
return aItem->
Type() ==
PCB_VIA_T;
2756SHOWMATCH_DOMAIN_SPEC getShowMatchDomainSpec(
DRC_CONSTRAINT_T aConstraint )
2758 switch( aConstraint )
2775 return { SHOWMATCH_DOMAIN::SILK_ITEMS, SHOWMATCH_DOMAIN::SILK_TARGET_ITEMS,
true,
false };
2809 default:
return { SHOWMATCH_DOMAIN::ALL_ITEMS };
2814std::vector<BOARD_ITEM*> collectShowMatchCandidates(
BOARD* aBoard, SHOWMATCH_DOMAIN aDomain )
2816 std::vector<BOARD_ITEM*> items;
2823 if( matchesShowMatchDomain( item, aDomain ) )
2824 items.push_back( item );
2831std::vector<PCB_LAYER_ID> getShowMatchLayers(
const BOARD_ITEM* aItem )
2833 std::vector<PCB_LAYER_ID> layers;
2835 switch( aItem->
Type() )
2837 case PCB_PAD_T: layers =
static_cast<const PAD*
>( aItem )->Padstack().UniqueLayers();
break;
2839 case PCB_VIA_T: layers =
static_cast<const PCB_VIA*
>( aItem )->Padstack().UniqueLayers();
break;
2843 layers.push_back( layer );
2848 if( layers.empty() )
2858 bool testedLayer =
false;
2860 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItem ) )
2885std::vector<PCB_LAYER_ID> getShowMatchPairLayers(
const DRC_RULE& aRule,
const BOARD_ITEM* aItemA,
2888 std::vector<PCB_LAYER_ID> layers;
2889 std::set<int> seenLayers;
2897 if( seenLayers.insert(
static_cast<int>( aLayer ) ).second )
2898 layers.push_back( aLayer );
2901 switch( aConstraint )
2904 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemA ) )
2912 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemA ) )
2915 for(
PCB_LAYER_ID layer : getShowMatchLayers( aItemB ) )
2921 if( layers.empty() )
2931 for(
PCB_LAYER_ID layer : getShowMatchPairLayers( aRule, aItemA, aItemB, aConstraint ) )
2949 if(
name == prov->GetName() )
2961 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine enter: expr='%s', constraint=%d" ),
2962 aExpression, (
int) aConstraint );
2964 std::vector<BOARD_ITEM*> matches;
2973 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine: compile failed" ) );
2980 if( std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_board->GetConnectivity() )
2982 if( std::shared_ptr<FROM_TO_CACHE> ftCache = connectivity->GetFromToCache() )
2987 size_t totalItems = 0;
2988 size_t skippedItems = 0;
2989 size_t noLayerItems = 0;
2990 size_t checkedItems = 0;
2992 for(
auto& [kiid, item] :
m_board->GetItemByIdCache() )
2997 switch( item->Type() )
3010 LSET itemLayers = item->GetLayerSet();
3012 if( itemLayers.none() )
3019 bool matched =
false;
3023 if( condition.
EvaluateFor( item,
nullptr,
static_cast<int>( aConstraint ), layer,
3026 matches.push_back( item );
3027 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
3028 wxS(
"[ShowMatches] engine: match type=%d kiid=%s layer=%d" ),
3029 (
int) item->Type(), kiid.AsString(), (
int) layer );
3036 if( !matched && matches.size() == 0 && checkedItems <= 5 )
3038 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
3039 wxS(
"[ShowMatches] engine: no-match sample type=%d kiid=%s layers=%s" ),
3040 (
int) item->Type(), kiid.AsString(), itemLayers.
FmtHex() );
3044 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ),
3045 wxS(
"[ShowMatches] engine stats: total=%zu skipped=%zu noLayer=%zu checked=%zu" ),
3046 totalItems, skippedItems, noLayerItems, checkedItems );
3048 wxLogTrace( wxS(
"KI_TRACE_DRC_RULE_EDITOR" ), wxS(
"[ShowMatches] engine exit: total=%zu" ), matches.size() );
3055 std::vector<BOARD_ITEM*> matches;
3060 const bool requiresPairwise = aRule->m_Condition && aRule->m_Condition->RequiresPairItems();
3061 std::set<BOARD_ITEM*> matchedItems;
3063 if( std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_board->GetConnectivity() )
3065 if( std::shared_ptr<FROM_TO_CACHE> ftCache = connectivity->GetFromToCache() )
3074 SHOWMATCH_DOMAIN_SPEC domainSpec = getShowMatchDomainSpec( constraint.
m_Type );
3075 std::vector<BOARD_ITEM*> primaryItems = collectShowMatchCandidates(
m_board, domainSpec.primary );
3076 std::vector<BOARD_ITEM*> secondaryItems;
3078 if( domainSpec.hasSecondary )
3079 secondaryItems = collectShowMatchCandidates(
m_board, domainSpec.secondary );
3081 if( requiresPairwise )
3083 if( secondaryItems.empty() )
3085 for(
size_t ii = 0; ii < primaryItems.size(); ++ii )
3089 for(
size_t jj = ii + 1; jj < primaryItems.size(); ++jj )
3093 if( ruleMatchesPair( *aRule, itemA, itemB, constraint.
m_Type,
3096 matchedItems.insert( itemA );
3097 matchedItems.insert( itemB );
3108 if( itemA == itemB )
3111 if( ruleMatchesPair( *aRule, itemA, itemB, constraint.
m_Type,
3114 matchedItems.insert( itemA );
3115 matchedItems.insert( itemB );
3125 if( ruleMatchesUnary( *aRule, item, constraint.
m_Type, aReporter ? aReporter :
m_logReporter ) )
3127 matchedItems.insert( item );
3131 if( domainSpec.hasSecondary && domainSpec.secondaryUnary )
3135 if( ruleMatchesUnary( *aRule, item, constraint.
m_Type, aReporter ? aReporter :
m_logReporter ) )
3137 matchedItems.insert( item );
3144 matches.assign( matchedItems.begin(), matchedItems.end() );
3174 const PAD*
pad =
static_cast<const PAD*
>( aItem );
3189 *aSource = constraint.
GetName();
3219 std::erase_if(
m_ownClearanceCache, [&aUuid](
const auto& entry ) {
return entry.first.m_uuid == aUuid; } );
3241 using CLEARANCE_MAP = std::unordered_map<DRC_OWN_CLEARANCE_CACHE_KEY, int>;
3245 std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>> itemsToProcess;
3246 size_t estimatedPads = 0;
3249 estimatedPads += footprint->Pads().size();
3251 itemsToProcess.reserve(
m_board->Tracks().size() + estimatedPads * 2 );
3258 itemsToProcess.emplace_back( track, layer );
3262 itemsToProcess.emplace_back( track, track->GetLayer() );
3268 for(
PAD*
pad : footprint->Pads() )
3271 itemsToProcess.emplace_back(
pad, layer );
3275 if( itemsToProcess.empty() )
3286 [
this](
size_t aStart,
size_t aEnd,
const std::vector<std::pair<const BOARD_ITEM*, PCB_LAYER_ID>>& aItems )
3289 CLEARANCE_MAP localCache;
3291 for(
size_t i = aStart; i < aEnd; ++i )
3300 const PAD*
pad =
static_cast<const PAD*
>( item );
3319 auto results =
tp.submit_blocks( 0, itemsToProcess.size(),
3320 [&](
size_t aStart,
size_t aEnd ) -> CLEARANCE_MAP
3322 return processItems( aStart, aEnd, itemsToProcess );
3329 std::vector<CLEARANCE_MAP> collectedResults;
3330 collectedResults.reserve( results.size() );
3332 for(
size_t i = 0; i < results.size(); ++i )
3334 if( results[i].valid() )
3335 collectedResults.push_back( results[i].get() );
3342 for(
const auto& localCache : collectedResults )
constexpr EDA_IU_SCALE pcbIUScale
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
#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.
const std::unordered_map< KIID, BOARD_ITEM * > & GetItemByIdCache() const
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 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.
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(),...
@ 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
@ TEXT_THICKNESS_CONSTRAINT
@ NET_CHAIN_RETURN_PATH_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ MICROVIA_ASPECT_RATIO_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
#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:
@ 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