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() );
81 m_designSettings ( aSettings ),
83 m_drawingSheet( nullptr ),
84 m_schematicNetlist( nullptr ),
85 m_rulesValid( false ),
86 m_reportAllTrackErrors( false ),
87 m_testFootprints( false ),
88 m_logReporter( nullptr ),
89 m_progressReporter( nullptr )
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 );
406 makeNetclassRules( bds.
m_NetSettings->GetDefaultNetclass(),
true );
409 makeNetclassRules( netclass,
false );
411 for(
const auto& [
name, netclass] : bds.
m_NetSettings->GetCompositeNetclasses() )
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
511 while(
char* line = lineReader.
ReadLine() )
521 for( std::shared_ptr<DRC_RULE>& rule : rules )
535 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
539 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
541 condition = rule->m_Condition;
552 engineConstraint->
layerTest = rule->m_LayerCondition;
569 m_logReporter->
Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
571 provider->SetDRCEngine(
this );
604 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
607 throw original_parse_error;
644 if( !cacheGenerator.
Run() )
655 m_logReporter->
Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
657 if( !provider->RunTests( aUnits ) )
670#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
678 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
686 pad =
static_cast<const PAD*
>( a );
688 pad =
static_cast<const PAD*
>( b );
690 if(
pad &&
pad->GetAttribute() == PAD_ATTRIB::PTH )
696 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
724 const ZONE* zone =
nullptr;
725 const FOOTPRINT* parentFootprint =
nullptr;
735 pad =
static_cast<const PAD*
>( a );
737 zone =
static_cast<const ZONE*
>( a );
740 pad =
static_cast<const PAD*
>( b );
742 zone =
static_cast<const ZONE*
>( b );
745 parentFootprint =
pad->GetParentFootprint();
749 constraint.
m_Type = aConstraintType;
751 auto applyConstraint =
754 if( c->constraint.m_Value.HasMin() )
756 if( c->parentRule && c->parentRule->m_Implicit )
762 if( c->constraint.m_Value.HasOpt() )
765 if( c->constraint.m_Value.HasMax() )
766 constraint .m_Value.SetMax( c->constraint.m_Value.Max() );
768 switch( c->constraint.m_Type )
803 && ( ( ( !ac ) ^ ( !bc ) )
806 || ( ( footprints[0] == footprints[1] )
809 && !b_is_non_copper )
816 for(
int ii = 0; ii < 2; ++ii )
819 if( !footprints[ii] || !alt_items[ii] )
822 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
824 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
826 if( it != netcodes.end() )
829 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
830 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
832 constraint.
SetName(
_(
"net tie" ) );
842 int override_val = 0;
843 std::optional<int> overrideA;
844 std::optional<int> overrideB;
846 if( ac && !b_is_non_copper )
849 if( bc && !a_is_non_copper )
852 if( overrideA.has_value() || overrideB.has_value() )
856 if( overrideA.has_value() )
859 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
866 if( overrideB.has_value() )
869 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
873 if( overrideB > override_val )
881 if( override_val < m_designSettings->m_MinClearance )
884 msg =
_(
"board minimum" );
887 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
893 if( override_val < m_designSettings->m_HoleClearance )
896 msg =
_(
"board minimum hole" );
899 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
912 if(
pad &&
pad->GetLocalZoneConnection() != ZONE_CONNECTION::INHERITED )
918 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
929 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
932 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
935 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
946 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
949 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
952 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
961 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
973 std::optional<int>
override;
976 override =
pad->GetLocalSolderMaskMargin();
978 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
985 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
995 std::optional<int>
override;
998 override =
pad->GetLocalSolderPasteMargin();
1003 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1013 std::optional<double> overrideRatio;
1016 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1021 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1030 auto testAssertion =
1033 REPORT( wxString::Format(
_(
"Checking assertion \"%s\"." ),
1034 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1036 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer,
1039 REPORT(
_(
"Assertion passed." ) )
1047 auto processConstraint =
1050 bool implicit = c->parentRule && c->parentRule->m_Implicit;
1054 switch( c->constraint.m_Type )
1063 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1068 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1073 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1079 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1085 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1091 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1097 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1103 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute cleraance: %s." ),
1109 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1115 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1118 c->constraint.m_Value.Min() ) ) )
1122 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1140 wxString min = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1141 wxString opt = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1142 wxString max = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1149 switch( c->constraint.m_Type )
1152 if( c->constraint.m_Value.HasOpt() )
1154 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1158 else if( c->constraint.m_Value.HasMin() )
1160 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1168 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1174 if( c->constraint.m_Value.HasOpt() )
1176 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1180 else if( c->constraint.m_Value.HasMin() )
1182 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1189 if( c->constraint.m_Value.HasOpt() )
1191 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1195 else if( c->constraint.m_Value.HasMin() )
1197 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1207 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1213 if( c->constraint.m_Value.HasOpt() )
1215 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1219 else if( c->constraint.m_Value.HasMin() )
1221 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1229 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1235 REPORT( wxString::Format(
_(
"Checking %s." ),
1241 if( c->constraint.m_Value.HasMin() )
1244 if( c->constraint.m_Value.HasOpt() )
1247 if( c->constraint.m_Value.HasMax() )
1250 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1261 REPORT( wxString::Format(
_(
"Checking %s." ),
1267 if( a_is_non_copper || b_is_non_copper )
1271 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1273 else if( a_is_non_copper )
1275 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1278 else if( b_is_non_copper )
1280 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1299 switch(
static_cast<const PCB_VIA*
>( a )->GetViaType() )
1322 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1330 default: mask = 0;
break;
1334 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1337 REPORT(
_(
"Keepout constraint not met." ) )
1339 REPORT(
_(
"Disallow constraint not met." ) )
1357 if( !( c->layerTest & itemLayers ).any() )
1361 REPORT(
_(
"Keepout layer(s) not matched." ) )
1363 else if( c->parentRule )
1365 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1366 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1370 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1382 REPORT(
_(
"Constraint layer not matched." ) )
1384 else if( c->parentRule )
1386 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1387 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1391 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1398 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1401 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1407 REPORT(
_(
"Unconditional constraint applied." ) )
1411 REPORT(
_(
"Unconditional rule applied." ) )
1416 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1420 applyConstraint( c );
1430 REPORT( wxString::Format(
_(
"Checking rule condition \"%s\"." ),
1431 EscapeHTML( c->condition->GetExpression() ) ) )
1434 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1440 REPORT(
_(
"Constraint applied." ) )
1444 REPORT(
_(
"Rule applied." ) )
1449 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1453 applyConstraint( c );
1457 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1458 :
_(
"Condition not satisfied; rule ignored." ) )
1465 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1468 processConstraint( rule );
1485 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
1489 a = parentFootprint;
1491 b = parentFootprint;
1495 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1498 processConstraint( rule );
1508 constraint.
SetName(
_(
"board setup" ) );
1515 constraint.
SetName(
_(
"board setup" ) );
1522 constraint.
SetName(
_(
"board setup" ) );
1535 bool needBlankLine =
true;
1544 needBlankLine =
false;
1547 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1568 needBlankLine =
false;
1571 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1585 if( !a_is_non_copper && !b_is_non_copper )
1590 needBlankLine =
false;
1593 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1596 if( clearance < m_designSettings->m_MinClearance )
1599 constraint.
SetName(
_(
"board minimum" ) );
1609 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1615 constraint.
SetName(
_(
"board minimum" ) );
1623 if(
pad && parentFootprint )
1627 if( local != ZONE_CONNECTION::INHERITED )
1630 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
1635 constraint.
SetName(
_(
"footprint" ) );
1646 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
1663 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
1680 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
1710 auto testAssertion =
1713 REPORT( wxString::Format(
_(
"Checking rule assertion \"%s\"." ),
1714 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1716 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1719 REPORT(
_(
"Assertion passed." ) )
1724 aFailureHandler( &c->constraint );
1728 auto processConstraint =
1732 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
1736 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1737 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1740 if( !c->condition || c->condition->GetExpression().IsEmpty() )
1742 REPORT(
_(
"Unconditional rule applied." ) )
1747 REPORT( wxString::Format(
_(
"Checking rule condition \"%s\"." ),
1748 EscapeHTML( c->condition->GetExpression() ) ) )
1750 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1753 REPORT(
_(
"Rule applied." ) )
1758 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
1767 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1768 processConstraint( ruleset->at( ii ) );
1778 assert( error_code >= 0 && error_code <=
DRCE_LAST );
1786 static std::mutex globalLock;
1792 std::lock_guard<std::mutex> guard( globalLock );
1798 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
1799 aItem->GetViolatingTest()->GetName(),
1800 aItem->GetErrorMessage(),
1801 aItem->GetErrorCode() );
1803 DRC_RULE* rule = aItem->GetViolatingRule();
1806 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
1810 wxString violatingItemsStr = wxT(
"Violating items: " );
1859 wxSafeYield(
nullptr,
true );
1889 int current = c->constraint.GetValue().Min();
1891 if( current > worst )
1894 aConstraint = c->constraint;
1905 std::set<int> distinctMinimums;
1910 distinctMinimums.emplace( c->constraint.GetValue().Min() );
1913 return distinctMinimums;
1919 wxString& aBaseDpName )
1924 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
1928 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
1932 else if( ch ==
'+' )
1934 aComplementNet = wxT(
"-" );
1937 else if( ch ==
'-' )
1939 aComplementNet = wxT(
"+" );
1942 else if( ch ==
'N' )
1944 aComplementNet = wxT(
"P" );
1947 else if ( ch ==
'P' )
1949 aComplementNet = wxT(
"N" );
1958 if( rv != 0 && count >= 1 )
1960 aBaseDpName = aNetName.Left( aNetName.Length() - count );
1961 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
1971 wxString
dummy, coupledNetName;
2007 if( parentFootprint && parentFootprint->
IsNetTie() )
2014 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2016 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2030 if(
name == prov->GetName() )
constexpr EDA_IU_SCALE pcbIUScale
constexpr EDA_IU_SCALE unityScale
#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
bool Ignore(int aDRCErrorCode)
Return true if the DRC error code's severity is SEVERITY_IGNORE.
int m_SolderMaskExpansion
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
double m_SolderPasteMarginRatio
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.
const ZONES & Zones() const
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
void IncrementTimeStamp()
const FOOTPRINTS & Footprints() const
PROJECT * GetProject() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
void ForceComponentClassRecalculation() const
Forces the component class for all footprints to be recalculated.
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 ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer, DRC_CUSTOM_MARKER_HANDLER *aCustomHandler=nullptr)
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)
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)
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)
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
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)
virtual bool IsCancelled() const =0
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
virtual void AdvanceProgress()=0
Increment the progress bar length (inside the current virtual zone).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
virtual void SetMaxProgress(int aMaxProgress)=0
Fix the value that gives the 100 percent progress bar length (inside the current virtual zone).
virtual bool TextVarResolver(wxString *aToken) const
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
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)
std::function< void(PCB_MARKER *aMarker)> DRC_CUSTOM_MARKER_HANDLER
@ 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.
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.
std::vector< FAB_LAYER_COLOR > dummy
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
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)
wxString PrintZoneConnection(ZONE_CONNECTION aConnection)
ZONE_CONNECTION
How pads are covered by copper in zone.