54#define ERROR_LIMIT 199
55#define EXTENDED_ERROR_LIMIT 499
72 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
74 int setLevel = wxAtoi( valueStr );
76 if( level <= setLevel )
77 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
120 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
146 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
149 rule->m_Implicit =
true;
160 wxString expr, expr2, ncName;
168 rule->AddConstraint( widthConstraint );
172 rule->AddConstraint( connectionConstraint );
176 rule->AddConstraint( drillConstraint );
180 rule->AddConstraint( annulusConstraint );
184 rule->AddConstraint( diameterConstraint );
188 rule->AddConstraint( holeToHoleConstraint );
193 rule->AddConstraint( thermalSpokeCountConstraint );
199 rule->AddConstraint( silkClearanceConstraint );
205 rule->AddConstraint( silkTextHeightConstraint );
211 rule->AddConstraint( silkTextThicknessConstraint );
216 rule->AddConstraint( holeClearanceConstraint );
221 rule->AddConstraint( edgeClearanceConstraint );
226 rule->AddConstraint( courtyardClearanceConstraint );
230 std::shared_ptr<DRC_RULE> uViaRule =
createImplicitRule(
_(
"board setup micro-via constraints" ) );
236 uViaRule->AddConstraint( uViaDrillConstraint );
240 uViaRule->AddConstraint( uViaDiameterConstraint );
244 std::shared_ptr<DRC_RULE> barcodeRule =
createImplicitRule(
_(
"barcode visual separation default" ) );
247 barcodeRule->AddConstraint( barcodeSeparationConstraint );
252 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
253 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
255 auto makeNetclassRules =
256 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
258 ncName = nc->GetName();
259 ncName.Replace(
"'",
"\\'" );
261 if( nc->HasClearance() )
263 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
264 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
265 nc->GetClearanceParent()->GetHumanReadableName() );
266 netclassRule->m_Implicit =
true;
268 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
270 netclassClearanceRules.push_back( netclassRule );
274 netclassRule->AddConstraint( constraint );
277 if( nc->HasTrackWidth() )
279 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
280 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
281 nc->GetTrackWidthParent()->GetHumanReadableName() );
282 netclassRule->m_Implicit =
true;
284 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
286 netclassClearanceRules.push_back( netclassRule );
291 netclassRule->AddConstraint( constraint );
294 if( nc->HasDiffPairWidth() )
296 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
297 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
298 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
299 netclassRule->m_Implicit =
true;
301 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
303 netclassItemSpecificRules.push_back( netclassRule );
307 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
308 netclassRule->AddConstraint( constraint );
311 if( nc->HasDiffPairGap() )
313 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
314 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
315 nc->GetDiffPairGapParent()->GetHumanReadableName() );
316 netclassRule->m_Implicit =
true;
318 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
320 netclassItemSpecificRules.push_back( netclassRule );
325 netclassRule->AddConstraint( constraint );
328 if( nc->GetDiffPairGap() < nc->GetClearance() )
330 netclassRule = std::make_shared<DRC_RULE>();
331 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
332 nc->GetDiffPairGapParent()->GetHumanReadableName() );
333 netclassRule->m_Implicit =
true;
335 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
337 netclassItemSpecificRules.push_back( netclassRule );
340 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
341 netclassRule->AddConstraint( min_clearanceConstraint );
345 if( nc->HasViaDiameter() )
347 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
348 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
349 nc->GetViaDiameterParent()->GetHumanReadableName() );
350 netclassRule->m_Implicit =
true;
352 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
354 netclassItemSpecificRules.push_back( netclassRule );
359 netclassRule->AddConstraint( constraint );
362 if( nc->HasViaDrill() )
364 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
365 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
366 nc->GetViaDrillParent()->GetHumanReadableName() );
367 netclassRule->m_Implicit =
true;
369 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
371 netclassItemSpecificRules.push_back( netclassRule );
376 netclassRule->AddConstraint( constraint );
379 if( nc->HasuViaDiameter() )
381 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
382 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
383 nc->GetuViaDiameterParent()->GetHumanReadableName() );
384 netclassRule->m_Implicit =
true;
386 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
388 netclassItemSpecificRules.push_back( netclassRule );
392 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
393 netclassRule->AddConstraint( constraint );
396 if( nc->HasuViaDrill() )
398 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
399 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
400 nc->GetuViaDrillParent()->GetHumanReadableName() );
401 netclassRule->m_Implicit =
true;
403 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
405 netclassItemSpecificRules.push_back( netclassRule );
410 netclassRule->AddConstraint( constraint );
414 m_board->SynchronizeNetsAndNetClasses(
false );
418 makeNetclassRules( netclass,
false );
421 makeNetclassRules( netclass,
false );
428 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
429 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
431 return lhs->m_Constraints[0].m_Value.Min()
432 < rhs->m_Constraints[0].m_Value.Min();
435 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
438 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
442 auto addTuningSingleRule =
444 const wxString& aNetclassName )
449 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
450 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
451 tuningRule->m_Implicit =
true;
453 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s'" ),
461 tuningRule->AddConstraint( constraint );
466 auto addTuningDifferentialRules =
473 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
474 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
475 tuningRule->m_Implicit =
true;
477 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
478 aNetclass->GetName(),
485 tuningRule->AddConstraint( constraint );
489 std::shared_ptr<DRC_RULE> tuningRule2 = std::make_shared<DRC_RULE>();
490 tuningRule2->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
491 tuningRule2->m_Implicit =
true;
493 expr2 = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
494 aNetclass->GetName(),
501 tuningRule2->AddConstraint( constraint2 );
508 std::shared_ptr<DRC_RULE> diffPairClearanceRule = std::make_shared<DRC_RULE>();
509 diffPairClearanceRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
510 diffPairClearanceRule->m_Implicit =
true;
512 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
513 aNetclass->GetName(),
519 diffPairClearanceRule->AddConstraint( min_clearanceConstraint );
521 addRule( diffPairClearanceRule );
527 std::shared_ptr<TUNING_PROFILES> tuningParams =
project->GetProjectFile().TuningProfileParameters();
529 auto addNetclassTuningProfileRules =
530 [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules](
NETCLASS* aNetclass )
532 if( aNetclass->HasTuningProfile() )
534 const wxString delayProfileName = aNetclass->GetTuningProfile();
535 const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName );
546 addTuningSingleRule( entry, delayProfileName, aNetclass->GetName() );
548 addTuningDifferentialRules( entry, delayProfileName, aNetclass );
556 addNetclassTuningProfileRules( netclass.get() );
559 addNetclassTuningProfileRules( netclass.get() );
563 auto addKeepoutZoneRule =
595 rule->m_ImplicitItemId = zone->
m_Uuid;
597 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsArea('%s')" ),
602 int disallowFlags = 0;
621 rule->AddConstraint( disallowConstraint );
627 addKeepoutZoneRule( zone,
nullptr );
632 for(
ZONE* zone : footprint->Zones() )
635 addKeepoutZoneRule( zone, footprint );
643 if(
m_board && aPath.FileExists() )
645 std::vector<std::shared_ptr<DRC_RULE>> rules;
647 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
652 std::function<bool( wxString* )>
resolver =
653 [&]( wxString* token ) ->
bool
655 return m_board->ResolveTextVar( token, 0 );
658 while(
char* line = lineReader.
ReadLine() )
660 wxString str( line );
661 str =
m_board->ConvertCrossReferencesToKIIDs( str );
664 rulesText << str <<
'\n';
674 for( std::shared_ptr<DRC_RULE>& rule : rules )
687 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
691 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
693 condition = rule->m_Condition;
694 condition->
Compile( &error_semaphore );
699 TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
708 engineConstraint->
layerTest = rule->m_LayerCondition;
725 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
727 provider->SetDRCEngine(
this );
762 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
765 throw original_parse_error;
802 if( !cacheGenerator.
Run() )
806 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
808 int timestamp =
m_board->GetTimeStamp();
813 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
815 if( !provider->RunTests( aUnits ) )
824 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
828#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
836 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
844 pad =
static_cast<const PAD*
>( a );
846 pad =
static_cast<const PAD*
>( b );
854 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
882 const ZONE* zone =
nullptr;
883 const FOOTPRINT* parentFootprint =
nullptr;
893 pad =
static_cast<const PAD*
>( a );
895 zone =
static_cast<const ZONE*
>( a );
898 pad =
static_cast<const PAD*
>( b );
900 zone =
static_cast<const ZONE*
>( b );
903 parentFootprint =
pad->GetParentFootprint();
907 constraint.
m_Type = aConstraintType;
909 auto applyConstraint =
912 if( c->constraint.m_Value.HasMin() )
914 if( c->parentRule && c->parentRule->m_Implicit )
920 if( c->constraint.m_Value.HasOpt() )
923 if( c->constraint.m_Value.HasMax() )
926 switch( c->constraint.m_Type )
961 && ( ( ( !ac ) ^ ( !bc ) )
964 || ( ( footprints[0] == footprints[1] )
967 && !b_is_non_copper )
974 for(
int ii = 0; ii < 2; ++ii )
977 if( !footprints[ii] || !alt_items[ii] )
980 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
982 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
984 if( it != netcodes.end() )
987 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
988 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
990 constraint.
SetName(
_(
"net tie" ) );
1000 int override_val = 0;
1001 std::optional<int> overrideA;
1002 std::optional<int> overrideB;
1004 if( ac && !b_is_non_copper )
1007 if( bc && !a_is_non_copper )
1010 if( overrideA.has_value() || overrideB.has_value() )
1014 if( overrideA.has_value() )
1017 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1024 if( overrideB.has_value() )
1027 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1031 if( overrideB > override_val )
1039 if( override_val < m_designSettings->m_MinClearance )
1042 msg =
_(
"board minimum" );
1045 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1051 if( override_val < m_designSettings->m_HoleClearance )
1054 msg =
_(
"board minimum hole" );
1057 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
1076 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
1087 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
1090 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
1093 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
1104 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
1107 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
1110 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
1119 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
1131 std::optional<int>
override;
1134 override =
pad->GetLocalSolderMaskMargin();
1136 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
1143 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1153 std::optional<int>
override;
1156 override =
pad->GetLocalSolderPasteMargin();
1161 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1171 std::optional<double> overrideRatio;
1174 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1179 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1188 auto testAssertion =
1191 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1192 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1194 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer,
1197 REPORT(
_(
"Assertion passed." ) )
1205 auto processConstraint =
1208 bool implicit = c->parentRule && c->parentRule->m_Implicit;
1212 switch( c->constraint.m_Type )
1221 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1226 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1231 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1237 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1243 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1249 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1255 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1261 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute clearance: %s." ),
1267 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1273 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1276 c->constraint.m_Value.Min() ) ) )
1280 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1298 wxString min = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1299 wxString opt = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1300 wxString max = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1307 switch( c->constraint.m_Type )
1310 if( c->constraint.m_Value.HasOpt() )
1312 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1316 else if( c->constraint.m_Value.HasMin() )
1318 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1326 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1332 if( c->constraint.m_Value.HasOpt() )
1334 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1338 else if( c->constraint.m_Value.HasMin() )
1340 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1347 if( c->constraint.m_Value.HasOpt() )
1349 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1353 else if( c->constraint.m_Value.HasMin() )
1355 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1365 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1371 if( c->constraint.m_Value.HasOpt() )
1373 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1377 else if( c->constraint.m_Value.HasMin() )
1379 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1387 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1393 REPORT( wxString::Format(
_(
"Checking %s." ),
1399 if( c->constraint.m_Value.HasMin() )
1402 if( c->constraint.m_Value.HasOpt() )
1405 if( c->constraint.m_Value.HasMax() )
1408 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1419 REPORT( wxString::Format(
_(
"Checking %s." ),
1425 if( a_is_non_copper || b_is_non_copper )
1429 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1431 else if( a_is_non_copper )
1433 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1436 else if( b_is_non_copper )
1438 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1457 if(
via->IsMicroVia() )
1459 else if(
via->IsBlindVia() )
1461 else if(
via->IsBuriedVia() )
1483 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1491 default: mask = 0;
break;
1495 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1498 REPORT(
_(
"Keepout constraint not met." ) )
1500 REPORT(
_(
"Disallow constraint not met." ) )
1518 if( !( c->layerTest & itemLayers ).any() )
1522 REPORT(
_(
"Keepout layer(s) not matched." ) )
1524 else if( c->parentRule )
1526 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1527 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1531 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1539 || (
m_board->GetEnabledLayers() & c->layerTest ).count() == 0 )
1543 REPORT(
_(
"Constraint layer not matched." ) )
1545 else if( c->parentRule )
1547 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1548 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1552 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1559 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1562 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1568 REPORT(
_(
"Unconditional constraint applied." ) )
1572 REPORT(
_(
"Unconditional rule applied." ) )
1577 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1581 applyConstraint( c );
1591 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1592 EscapeHTML( c->condition->GetExpression() ) ) )
1595 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1601 REPORT(
_(
"Constraint applied." ) )
1605 REPORT(
_(
"Rule applied." ) )
1610 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1614 applyConstraint( c );
1618 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1619 :
_(
"Condition not satisfied; rule ignored." ) )
1626 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1629 processConstraint( rule );
1646 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
1650 a = parentFootprint;
1652 b = parentFootprint;
1656 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1659 processConstraint( rule );
1669 constraint.
SetName(
_(
"board setup" ) );
1676 constraint.
SetName(
_(
"board setup" ) );
1683 constraint.
SetName(
_(
"board setup" ) );
1696 bool needBlankLine =
true;
1705 needBlankLine =
false;
1708 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1729 needBlankLine =
false;
1732 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1746 if( !a_is_non_copper && !b_is_non_copper )
1751 needBlankLine =
false;
1754 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1760 constraint.
SetName(
_(
"board minimum" ) );
1770 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1776 constraint.
SetName(
_(
"board minimum" ) );
1784 if(
pad && parentFootprint )
1791 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
1796 constraint.
SetName(
_(
"footprint" ) );
1807 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
1824 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
1841 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
1871 auto testAssertion =
1874 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
1875 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1877 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1880 REPORT(
_(
"Assertion passed." ) )
1885 aFailureHandler( &c->constraint );
1889 auto processConstraint =
1893 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
1897 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1898 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1901 if( !c->condition || c->condition->GetExpression().IsEmpty() )
1903 REPORT(
_(
"Unconditional rule applied." ) )
1908 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1909 EscapeHTML( c->condition->GetExpression() ) ) )
1911 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1914 REPORT(
_(
"Rule applied." ) )
1919 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
1928 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1929 processConstraint( ruleset->at( ii ) );
1939 assert( error_code >= 0 && error_code <=
DRCE_LAST );
1945 int aMarkerLayer,
const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
1947 static std::mutex globalLock;
1953 std::lock_guard<std::mutex> guard( globalLock );
1959 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
1960 aItem->GetViolatingTest()->GetName(),
1961 aItem->GetErrorMessage(),
1962 aItem->GetErrorCode() );
1964 DRC_RULE* rule = aItem->GetViolatingRule();
1967 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
1971 wxString violatingItemsStr = wxT(
"Violating items: " );
1973 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
2020 wxSafeYield(
nullptr,
true );
2050 int current = c->constraint.GetValue().Min();
2052 if( current > worst )
2055 aConstraint = c->constraint;
2066 std::set<int> distinctMinimums;
2071 distinctMinimums.emplace( c->constraint.GetValue().Min() );
2074 return distinctMinimums;
2080 wxString& aBaseDpName )
2085 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2089 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
2093 else if( ch ==
'+' )
2095 aComplementNet = wxT(
"-" );
2098 else if( ch ==
'-' )
2100 aComplementNet = wxT(
"+" );
2103 else if( ch ==
'N' )
2105 aComplementNet = wxT(
"P" );
2108 else if ( ch ==
'P' )
2110 aComplementNet = wxT(
"N" );
2119 if( rv != 0 && count >= 1 )
2121 aBaseDpName = aNetName.Left( aNetName.Length() - count );
2122 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
2132 wxString
dummy, coupledNetName;
2168 if( parentFootprint && parentFootprint->
IsNetTie() )
2175 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2177 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2191 if(
name == prov->GetName() )
2203 std::vector<BOARD_ITEM*> matches;
2215 for(
auto& [kiid, item] :
m_board->GetItemByIdCache() )
2217 LSET itemLayers = item->GetLayerSet();
2221 if( condition.
EvaluateFor( item,
nullptr,
static_cast<int>( aConstraint ), layer,
2224 matches.push_back( item );
constexpr EDA_IU_SCALE pcbIUScale
constexpr EDA_IU_SCALE unityScale
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
#define MAXIMUM_CLEARANCE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual std::optional< int > GetClearanceOverrides(wxString *aSource) const
Return any clearance overrides set in the "classic" (ie: pre-rule) system.
virtual std::optional< int > GetLocalClearance() const
Return any local clearances set in the "classic" (ie: pre-rule) system.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
int m_CopperEdgeClearance
int m_MinSilkTextThickness
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
int m_ViasMinAnnularWidth
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
virtual bool HasDrilledHole() const
virtual bool IsOnCopperLayer() const
Information pertinent to a Pcbnew printed circuit board.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Represents a single line in a time domain profile track propagation setup.
int GetDiffPairGap() const
PCB_LAYER_ID GetSignalLayer() const
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
void SetParentRule(DRC_RULE *aParentRule)
MINOPTMAX< int > & Value()
ZONE_CONNECTION m_ZoneConnection
void SetName(const wxString &aName)
void SetOptionsFromOther(const DRC_CONSTRAINT &aOther)
DRC_RULE * GetParentRule() const
std::map< DRC_CONSTRAINT_T, std::vector< DRC_ENGINE_CONSTRAINT * > * > m_constraintMap
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
void addRule(std::shared_ptr< DRC_RULE > &rule)
PROGRESS_REPORTER * m_progressReporter
void loadRules(const wxFileName &aPath)
Load and parse a rule set from an sexpr text file.
std::vector< DRC_TEST_PROVIDER * > m_testProviders
std::set< int > QueryDistinctConstraints(DRC_CONSTRAINT_T aConstraintId)
DS_PROXY_VIEW_ITEM * m_drawingSheet
NETLIST * m_schematicNetlist
bool KeepRefreshing(bool aWait=false)
bool m_reportAllTrackErrors
bool ReportProgress(double aProgress)
DRC_TEST_PROVIDER * GetTestProvider(const wxString &name) const
bool HasRulesForConstraintType(DRC_CONSTRAINT_T constraintID)
BOARD_DESIGN_SETTINGS * GetDesignSettings() const
void SetMaxProgress(int aSize)
DRC_ENGINE(BOARD *aBoard=nullptr, BOARD_DESIGN_SETTINGS *aSettings=nullptr)
std::vector< int > m_errorLimits
bool IsErrorLimitExceeded(int error_code)
void ProcessAssertions(const BOARD_ITEM *a, std::function< void(const DRC_CONSTRAINT *)> aFailureHandler, REPORTER *aReporter=nullptr)
DRC_VIOLATION_HANDLER m_violationHandler
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
std::vector< std::shared_ptr< DRC_RULE > > m_rules
std::shared_ptr< DRC_RULE > createImplicitRule(const wxString &name)
static bool IsNetADiffPair(BOARD *aBoard, NETINFO_ITEM *aNet, int &aNetP, int &aNetN)
bool IsNetTieExclusion(int aTrackNetCode, PCB_LAYER_ID aTrackLayer, const VECTOR2I &aCollisionPos, BOARD_ITEM *aCollidingItem)
Check if the given collision between a track and another item occurs during the track's entry into a ...
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint)
std::vector< BOARD_ITEM * > GetItemsMatchingCondition(const wxString &aExpression, DRC_CONSTRAINT_T aConstraint=ASSERTION_CONSTRAINT, REPORTER *aReporter=nullptr)
Evaluate a DRC condition against all board items and return matches.
void InitEngine(const wxFileName &aRulePath)
Initialize the DRC engine.
DRC_CONSTRAINT EvalZoneConnection(const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
static int MatchDpSuffix(const wxString &aNetName, wxString &aComplementNet, wxString &aBaseDpName)
Check if the given net is a diff pair, returning its polarity and complement if so.
bool ReportPhase(const wxString &aMessage)
BOARD_DESIGN_SETTINGS * m_designSettings
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator={})
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
bool EvaluateFor(const BOARD_ITEM *aItemA, const BOARD_ITEM *aItemB, int aConstraint, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
std::vector< DRC_TEST_PROVIDER * > GetTestProviders() const
static DRC_TEST_PROVIDER_REGISTRY & Instance()
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out DRC_ITEM and posi...
void SetDRCEngine(DRC_ENGINE *engine)
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
KICAD_T Type() const
Returns the type of object.
EDA_ITEM_FLAGS GetFlags() const
A LINE_READER that reads from an open file.
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
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 & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
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.
Handle the data for a net.
const wxString & GetNetname() const
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetCompositeNetclasses() const
Gets all composite (multiple assignment / missing defaults) netclasses.
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetNetclasses() const
Gets all netclasses.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
std::optional< int > GetLocalSolderMaskMargin() const
A small class to help profiling.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
double msecs(bool aSinceLast=false)
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
UNITS_PROVIDER(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
Handle a list of polygons defining a copper zone.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
bool GetDoNotAllowVias() const
bool GetDoNotAllowPads() const
bool GetDoNotAllowTracks() const
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, int aFlags)
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)
@ DRC_DISALLOW_BURIED_VIAS
@ DRC_DISALLOW_BLIND_VIAS
@ DRC_DISALLOW_THROUGH_VIAS
@ DRC_DISALLOW_FOOTPRINTS
@ DRC_DISALLOW_MICRO_VIAS
@ ANNULAR_WIDTH_CONSTRAINT
@ COURTYARD_CLEARANCE_CONSTRAINT
@ VIA_DIAMETER_CONSTRAINT
@ ZONE_CONNECTION_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ MIN_RESOLVED_SPOKES_CONSTRAINT
@ TEXT_THICKNESS_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
@ CONNECTION_WIDTH_CONSTRAINT
@ THERMAL_RELIEF_GAP_CONSTRAINT
@ MAX_UNCOUPLED_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_ABS_MARGIN_CONSTRAINT
@ SOLDER_MASK_EXPANSION_CONSTRAINT
@ PHYSICAL_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_REL_MARGIN_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
constexpr int DRC_DISALLOW_VIAS
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
static FILENAME_RESOLVER * resolver
static const wxChar * traceDrcProfile
Flag to enable DRC profile timing logging.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
PCB_LAYER_ID
A quick note on layer IDs:
KICOMMON_API wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
@ PTH
Plated through hole pad.
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::shared_ptr< DRC_RULE > parentRule
DRC_RULE_CONDITION * condition
DRC_CONSTRAINT constraint
A filename or source description, a problem input line, a line number, a byte offset,...
Represents a single line in the tuning profile configuration grid.
bool m_GenerateNetClassDRCRules
std::vector< DELAY_PROFILE_TRACK_PROPAGATION_ENTRY > m_TrackPropagationEntries
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I
wxString PrintZoneConnection(ZONE_CONNECTION aConnection)
ZONE_CONNECTION
How pads are covered by copper in zone.
@ THERMAL
Use thermal relief for pads.
@ THT_THERMAL
Thermal relief only for THT pads.
@ FULL
pads are covered by copper