51#define ERROR_LIMIT 199
52#define EXTENDED_ERROR_LIMIT 499
69 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
71 int setLevel = wxAtoi( valueStr );
73 if( level <= setLevel )
74 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
117 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
143 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
146 rule->m_Implicit =
true;
164 rule->AddConstraint( widthConstraint );
168 rule->AddConstraint( connectionConstraint );
172 rule->AddConstraint( drillConstraint );
176 rule->AddConstraint( annulusConstraint );
180 rule->AddConstraint( diameterConstraint );
184 rule->AddConstraint( holeToHoleConstraint );
189 rule->AddConstraint( thermalSpokeCountConstraint );
195 rule->AddConstraint( silkClearanceConstraint );
201 rule->AddConstraint( silkTextHeightConstraint );
207 rule->AddConstraint( silkTextThicknessConstraint );
212 rule->AddConstraint( holeClearanceConstraint );
217 rule->AddConstraint( edgeClearanceConstraint );
222 rule->AddConstraint( courtyardClearanceConstraint );
226 std::shared_ptr<DRC_RULE> uViaRule =
createImplicitRule(
_(
"board setup micro-via constraints" ) );
232 uViaRule->AddConstraint( uViaDrillConstraint );
236 uViaRule->AddConstraint( uViaDiameterConstraint );
240 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
241 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
243 auto makeNetclassRules =
244 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
246 wxString ncName = nc->GetName();
249 ncName.Replace(
"'",
"\\'" );
251 if( nc->HasClearance() )
253 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
254 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
255 nc->GetClearanceParent()->GetHumanReadableName() );
256 netclassRule->m_Implicit =
true;
258 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
260 netclassClearanceRules.push_back( netclassRule );
264 netclassRule->AddConstraint( constraint );
267 if( nc->HasTrackWidth() )
269 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
270 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
271 nc->GetTrackWidthParent()->GetHumanReadableName() );
272 netclassRule->m_Implicit =
true;
274 expr = wxString::Format( wxT(
"A.NetClass == '%s'" ), ncName );
276 netclassClearanceRules.push_back( netclassRule );
281 netclassRule->AddConstraint( constraint );
284 if( nc->HasDiffPairWidth() )
286 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
287 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
288 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
289 netclassRule->m_Implicit =
true;
291 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.inDiffPair('*')" ), ncName );
293 netclassItemSpecificRules.push_back( netclassRule );
297 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
298 netclassRule->AddConstraint( constraint );
301 if( nc->HasDiffPairGap() )
303 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
304 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
305 nc->GetDiffPairGapParent()->GetHumanReadableName() );
306 netclassRule->m_Implicit =
true;
308 expr = wxString::Format( wxT(
"A.NetClass == '%s'" ), ncName );
310 netclassItemSpecificRules.push_back( netclassRule );
315 netclassRule->AddConstraint( constraint );
318 if( nc->GetDiffPairGap() < nc->GetClearance() )
320 netclassRule = std::make_shared<DRC_RULE>();
321 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
322 nc->GetDiffPairGapParent()->GetHumanReadableName() );
323 netclassRule->m_Implicit =
true;
325 expr = wxString::Format( wxT(
"A.NetClass == '%s' && AB.isCoupledDiffPair()" ),
328 netclassItemSpecificRules.push_back( netclassRule );
331 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
332 netclassRule->AddConstraint( min_clearanceConstraint );
336 if( nc->HasViaDiameter() )
338 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
339 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
340 nc->GetViaDiameterParent()->GetHumanReadableName() );
341 netclassRule->m_Implicit =
true;
343 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type != 'Micro'" ), ncName );
345 netclassItemSpecificRules.push_back( netclassRule );
350 netclassRule->AddConstraint( constraint );
353 if( nc->HasViaDrill() )
355 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
356 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
357 nc->GetViaDrillParent()->GetHumanReadableName() );
358 netclassRule->m_Implicit =
true;
360 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type != 'Micro'" ), ncName );
362 netclassItemSpecificRules.push_back( netclassRule );
367 netclassRule->AddConstraint( constraint );
370 if( nc->HasuViaDiameter() )
372 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
373 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
374 nc->GetuViaDiameterParent()->GetHumanReadableName() );
375 netclassRule->m_Implicit =
true;
377 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type == 'Micro'" ), ncName );
379 netclassItemSpecificRules.push_back( netclassRule );
383 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
384 netclassRule->AddConstraint( constraint );
387 if( nc->HasuViaDrill() )
389 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
390 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
391 nc->GetuViaDrillParent()->GetHumanReadableName() );
392 netclassRule->m_Implicit =
true;
394 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type == 'Micro'" ), ncName );
396 netclassItemSpecificRules.push_back( netclassRule );
401 netclassRule->AddConstraint( constraint );
405 m_board->SynchronizeNetsAndNetClasses(
false );
409 makeNetclassRules( netclass,
false );
412 makeNetclassRules( netclass,
false );
419 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
420 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
422 return lhs->m_Constraints[0].m_Value.Min()
423 < rhs->m_Constraints[0].m_Value.Min();
426 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
429 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
434 std::vector<ZONE*> keepoutZones;
439 keepoutZones.push_back( zone );
444 for(
ZONE* zone : footprint->Zones() )
447 keepoutZones.push_back( zone );
451 for(
ZONE* zone : keepoutZones )
453 wxString
name = zone->GetZoneName();
460 rule->m_ImplicitItemId = zone->m_Uuid;
462 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsArea('%s')" ),
463 zone->m_Uuid.AsString() ) );
465 rule->m_LayerCondition = zone->GetLayerSet();
467 int disallowFlags = 0;
469 if( zone->GetDoNotAllowTracks() )
472 if( zone->GetDoNotAllowVias() )
475 if( zone->GetDoNotAllowPads() )
478 if( zone->GetDoNotAllowZoneFills() )
481 if( zone->GetDoNotAllowFootprints() )
486 rule->AddConstraint( disallowConstraint );
493 if( aPath.FileExists() )
495 std::vector<std::shared_ptr<DRC_RULE>> rules;
497 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
502 std::function<bool( wxString* )>
resolver =
503 [&]( wxString* token ) ->
bool
506 return m_board->GetProject()->TextVarResolver( token );
511 while(
char* line = lineReader.
ReadLine() )
521 for( std::shared_ptr<DRC_RULE>& rule : rules )
534 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
538 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
540 condition = rule->m_Condition;
541 condition->
Compile( &error_semaphore );
546 TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
555 engineConstraint->
layerTest = rule->m_LayerCondition;
572 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
574 provider->SetDRCEngine(
this );
609 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
612 throw original_parse_error;
649 if( !cacheGenerator.
Run() )
653 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
655 int timestamp =
m_board->GetTimeStamp();
660 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
662 if( !provider->RunTests( aUnits ) )
671 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
675#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
683 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
691 pad =
static_cast<const PAD*
>( a );
693 pad =
static_cast<const PAD*
>( b );
701 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
729 const ZONE* zone =
nullptr;
730 const FOOTPRINT* parentFootprint =
nullptr;
740 pad =
static_cast<const PAD*
>( a );
742 zone =
static_cast<const ZONE*
>( a );
745 pad =
static_cast<const PAD*
>( b );
747 zone =
static_cast<const ZONE*
>( b );
750 parentFootprint =
pad->GetParentFootprint();
754 constraint.
m_Type = aConstraintType;
756 auto applyConstraint =
759 if( c->constraint.m_Value.HasMin() )
761 if( c->parentRule && c->parentRule->m_Implicit )
767 if( c->constraint.m_Value.HasOpt() )
770 if( c->constraint.m_Value.HasMax() )
773 switch( c->constraint.m_Type )
808 && ( ( ( !ac ) ^ ( !bc ) )
811 || ( ( footprints[0] == footprints[1] )
814 && !b_is_non_copper )
821 for(
int ii = 0; ii < 2; ++ii )
824 if( !footprints[ii] || !alt_items[ii] )
827 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
829 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
831 if( it != netcodes.end() )
834 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
835 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
837 constraint.
SetName(
_(
"net tie" ) );
847 int override_val = 0;
848 std::optional<int> overrideA;
849 std::optional<int> overrideB;
851 if( ac && !b_is_non_copper )
854 if( bc && !a_is_non_copper )
857 if( overrideA.has_value() || overrideB.has_value() )
861 if( overrideA.has_value() )
864 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
871 if( overrideB.has_value() )
874 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
878 if( overrideB > override_val )
886 if( override_val < m_designSettings->m_MinClearance )
889 msg =
_(
"board minimum" );
892 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
898 if( override_val < m_designSettings->m_HoleClearance )
901 msg =
_(
"board minimum hole" );
904 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
923 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
934 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
937 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
940 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
951 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
954 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
957 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
966 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
978 std::optional<int>
override;
981 override =
pad->GetLocalSolderMaskMargin();
983 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
990 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1000 std::optional<int>
override;
1003 override =
pad->GetLocalSolderPasteMargin();
1008 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1018 std::optional<double> overrideRatio;
1021 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1026 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1035 auto testAssertion =
1038 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1039 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1041 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer,
1044 REPORT(
_(
"Assertion passed." ) )
1052 auto processConstraint =
1055 bool implicit = c->parentRule && c->parentRule->m_Implicit;
1059 switch( c->constraint.m_Type )
1068 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1073 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1078 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1084 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1090 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1096 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1102 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1108 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute cleraance: %s." ),
1114 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1120 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1123 c->constraint.m_Value.Min() ) ) )
1127 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1145 wxString min = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1146 wxString opt = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1147 wxString max = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1154 switch( c->constraint.m_Type )
1157 if( c->constraint.m_Value.HasOpt() )
1159 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1163 else if( c->constraint.m_Value.HasMin() )
1165 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1173 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1179 if( c->constraint.m_Value.HasOpt() )
1181 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1185 else if( c->constraint.m_Value.HasMin() )
1187 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1194 if( c->constraint.m_Value.HasOpt() )
1196 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1200 else if( c->constraint.m_Value.HasMin() )
1202 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1212 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1218 if( c->constraint.m_Value.HasOpt() )
1220 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1224 else if( c->constraint.m_Value.HasMin() )
1226 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1234 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1240 REPORT( wxString::Format(
_(
"Checking %s." ),
1246 if( c->constraint.m_Value.HasMin() )
1249 if( c->constraint.m_Value.HasOpt() )
1252 if( c->constraint.m_Value.HasMax() )
1255 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1266 REPORT( wxString::Format(
_(
"Checking %s." ),
1272 if( a_is_non_copper || b_is_non_copper )
1276 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1278 else if( a_is_non_copper )
1280 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1283 else if( b_is_non_copper )
1285 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1304 switch(
static_cast<const PCB_VIA*
>( a )->GetViaType() )
1327 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1335 default: mask = 0;
break;
1339 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1342 REPORT(
_(
"Keepout constraint not met." ) )
1344 REPORT(
_(
"Disallow constraint not met." ) )
1362 if( !( c->layerTest & itemLayers ).any() )
1366 REPORT(
_(
"Keepout layer(s) not matched." ) )
1368 else if( c->parentRule )
1370 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1371 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1375 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1383 || (
m_board->GetEnabledLayers() & c->layerTest ).count() == 0 )
1387 REPORT(
_(
"Constraint layer not matched." ) )
1389 else if( c->parentRule )
1391 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1392 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1396 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1403 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1406 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1412 REPORT(
_(
"Unconditional constraint applied." ) )
1416 REPORT(
_(
"Unconditional rule applied." ) )
1421 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1425 applyConstraint( c );
1435 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1436 EscapeHTML( c->condition->GetExpression() ) ) )
1439 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1445 REPORT(
_(
"Constraint applied." ) )
1449 REPORT(
_(
"Rule applied." ) )
1454 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1458 applyConstraint( c );
1462 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1463 :
_(
"Condition not satisfied; rule ignored." ) )
1470 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1473 processConstraint( rule );
1490 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
1494 a = parentFootprint;
1496 b = parentFootprint;
1500 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1503 processConstraint( rule );
1513 constraint.
SetName(
_(
"board setup" ) );
1520 constraint.
SetName(
_(
"board setup" ) );
1527 constraint.
SetName(
_(
"board setup" ) );
1540 bool needBlankLine =
true;
1549 needBlankLine =
false;
1552 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1573 needBlankLine =
false;
1576 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1590 if( !a_is_non_copper && !b_is_non_copper )
1595 needBlankLine =
false;
1598 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1604 constraint.
SetName(
_(
"board minimum" ) );
1614 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1620 constraint.
SetName(
_(
"board minimum" ) );
1628 if(
pad && parentFootprint )
1635 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
1640 constraint.
SetName(
_(
"footprint" ) );
1651 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
1668 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
1685 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
1715 auto testAssertion =
1718 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
1719 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1721 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1724 REPORT(
_(
"Assertion passed." ) )
1729 aFailureHandler( &c->constraint );
1733 auto processConstraint =
1737 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
1741 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1742 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1745 if( !c->condition || c->condition->GetExpression().IsEmpty() )
1747 REPORT(
_(
"Unconditional rule applied." ) )
1752 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1753 EscapeHTML( c->condition->GetExpression() ) ) )
1755 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1758 REPORT(
_(
"Rule applied." ) )
1763 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
1772 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1773 processConstraint( ruleset->at( ii ) );
1783 assert( error_code >= 0 && error_code <=
DRCE_LAST );
1789 int aMarkerLayer,
const std::vector<PCB_SHAPE>& aShapes )
1791 static std::mutex globalLock;
1797 std::lock_guard<std::mutex> guard( globalLock );
1803 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
1804 aItem->GetViolatingTest()->GetName(),
1805 aItem->GetErrorMessage(),
1806 aItem->GetErrorCode() );
1808 DRC_RULE* rule = aItem->GetViolatingRule();
1811 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
1815 wxString violatingItemsStr = wxT(
"Violating items: " );
1817 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
1864 wxSafeYield(
nullptr,
true );
1894 int current = c->constraint.GetValue().Min();
1896 if( current > worst )
1899 aConstraint = c->constraint;
1910 std::set<int> distinctMinimums;
1915 distinctMinimums.emplace( c->constraint.GetValue().Min() );
1918 return distinctMinimums;
1924 wxString& aBaseDpName )
1929 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
1933 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
1937 else if( ch ==
'+' )
1939 aComplementNet = wxT(
"-" );
1942 else if( ch ==
'-' )
1944 aComplementNet = wxT(
"+" );
1947 else if( ch ==
'N' )
1949 aComplementNet = wxT(
"P" );
1952 else if ( ch ==
'P' )
1954 aComplementNet = wxT(
"N" );
1963 if( rv != 0 && count >= 1 )
1965 aBaseDpName = aNetName.Left( aNetName.Length() - count );
1966 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
1976 wxString
dummy, coupledNetName;
2012 if( parentFootprint && parentFootprint->
IsNetTie() )
2019 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2021 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2035 if(
name == prov->GetName() )
2047 std::vector<BOARD_ITEM*> matches;
2059 for(
auto& [kiid, item] :
m_board->GetItemByIdCache() )
2061 LSET itemLayers = item->GetLayerSet();
2065 if( condition.
EvaluateFor( item,
nullptr,
static_cast<int>( aConstraint ), layer,
2068 matches.push_back( item );
constexpr EDA_IU_SCALE pcbIUScale
constexpr EDA_IU_SCALE unityScale
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
#define MAXIMUM_CLEARANCE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual std::optional< int > GetClearanceOverrides(wxString *aSource) const
Return any clearance overrides set in the "classic" (ie: pre-rule) system.
virtual std::optional< int > GetLocalClearance() const
Return any local clearances set in the "classic" (ie: pre-rule) system.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
int m_CopperEdgeClearance
int m_MinSilkTextThickness
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
int m_ViasMinAnnularWidth
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
virtual bool HasDrilledHole() const
virtual bool IsOnCopperLayer() const
Information pertinent to a Pcbnew printed circuit board.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
void SetParentRule(DRC_RULE *aParentRule)
MINOPTMAX< int > & Value()
ZONE_CONNECTION m_ZoneConnection
void SetName(const wxString &aName)
void SetOptionsFromOther(const DRC_CONSTRAINT &aOther)
DRC_RULE * GetParentRule() const
std::map< DRC_CONSTRAINT_T, std::vector< DRC_ENGINE_CONSTRAINT * > * > m_constraintMap
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
void addRule(std::shared_ptr< DRC_RULE > &rule)
PROGRESS_REPORTER * m_progressReporter
void loadRules(const wxFileName &aPath)
Load and parse a rule set from an sexpr text file.
std::vector< DRC_TEST_PROVIDER * > m_testProviders
std::set< int > QueryDistinctConstraints(DRC_CONSTRAINT_T aConstraintId)
DS_PROXY_VIEW_ITEM * m_drawingSheet
NETLIST * m_schematicNetlist
bool KeepRefreshing(bool aWait=false)
bool m_reportAllTrackErrors
bool ReportProgress(double aProgress)
DRC_TEST_PROVIDER * GetTestProvider(const wxString &name) const
bool HasRulesForConstraintType(DRC_CONSTRAINT_T constraintID)
BOARD_DESIGN_SETTINGS * GetDesignSettings() const
void SetMaxProgress(int aSize)
DRC_ENGINE(BOARD *aBoard=nullptr, BOARD_DESIGN_SETTINGS *aSettings=nullptr)
std::vector< int > m_errorLimits
bool IsErrorLimitExceeded(int error_code)
void ProcessAssertions(const BOARD_ITEM *a, std::function< void(const DRC_CONSTRAINT *)> aFailureHandler, REPORTER *aReporter=nullptr)
DRC_VIOLATION_HANDLER m_violationHandler
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
std::vector< std::shared_ptr< DRC_RULE > > m_rules
std::shared_ptr< DRC_RULE > createImplicitRule(const wxString &name)
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer, const std::vector< PCB_SHAPE > &aShapes={})
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 Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
bool EvaluateFor(const BOARD_ITEM *aItemA, const BOARD_ITEM *aItemB, int aConstraint, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
std::vector< DRC_TEST_PROVIDER * > GetTestProviders() const
static DRC_TEST_PROVIDER_REGISTRY & Instance()
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out DRC_ITEM and posi...
void SetDRCEngine(DRC_ENGINE *engine)
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
KICAD_T Type() const
Returns the type of object.
EDA_ITEM_FLAGS GetFlags() const
A LINE_READER that reads from an open file.
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
LSET is a set of PCB_LAYER_IDs.
static const LSET & FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
static const LSET & BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Handle the data for a net.
const wxString & GetNetname() const
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetCompositeNetclasses() const
Gets all composite (multiple assignment / missing defaults) netclasses.
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetNetclasses() const
Gets all netclasses.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
std::optional< int > GetLocalSolderMaskMargin() const
A small class to help profiling.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
double msecs(bool aSinceLast=false)
A pure virtual class used to derive REPORTER objects from.
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
UNITS_PROVIDER(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
Handle a list of polygons defining a copper zone.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
bool GetDoNotAllowVias() const
bool GetDoNotAllowPads() const
bool GetDoNotAllowTracks() const
int GetMinThickness() const
ZONE_CONNECTION GetPadConnection() const
int GetThermalReliefSpokeWidth() const
bool GetDoNotAllowFootprints() const
bool HasKeepoutParametersSet() const
Accessor to determine if any keepout parameters are set.
bool GetDoNotAllowZoneFills() const
int GetThermalReliefGap() const
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
void drcPrintDebugMessage(int level, const wxString &msg, const char *function, int line)
#define EXTENDED_ERROR_LIMIT
static bool isKeepoutZone(const BOARD_ITEM *aItem, bool aCheckFlags)
@ DRC_DISALLOW_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
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
static FILENAME_RESOLVER * resolver
static const wxChar * traceDrcProfile
Flag to enable DRC profile timing logging.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
PCB_LAYER_ID
A quick note on layer IDs:
KICOMMON_API wxString MessageTextFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A helper to convert the double length aValue to a string in inches, millimeters, or unscaled units.
@ PTH
Plated through hole pad.
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::shared_ptr< DRC_RULE > parentRule
DRC_RULE_CONDITION * condition
DRC_CONSTRAINT constraint
A filename or source description, a problem input line, a line number, a byte offset,...
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_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