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 );
147 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
150 rule->SetImplicitSource( aImplicitSource );
161 wxString expr, expr2, ncName;
165 std::shared_ptr<DRC_RULE> rule =
170 rule->AddConstraint( widthConstraint );
174 rule->AddConstraint( connectionConstraint );
178 rule->AddConstraint( drillConstraint );
182 rule->AddConstraint( annulusConstraint );
186 rule->AddConstraint( diameterConstraint );
190 rule->AddConstraint( holeToHoleConstraint );
196 rule->AddConstraint( thermalSpokeCountConstraint );
202 rule->AddConstraint( silkClearanceConstraint );
209 rule->AddConstraint( silkTextHeightConstraint );
216 rule->AddConstraint( silkTextThicknessConstraint );
221 rule->AddConstraint( holeClearanceConstraint );
226 rule->AddConstraint( edgeClearanceConstraint );
231 rule->AddConstraint( courtyardClearanceConstraint );
235 std::shared_ptr<DRC_RULE> uViaRule =
242 uViaRule->AddConstraint( uViaDrillConstraint );
246 uViaRule->AddConstraint( uViaDiameterConstraint );
250 std::shared_ptr<DRC_RULE> barcodeRule =
254 barcodeRule->AddConstraint( barcodeSeparationConstraint );
259 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
260 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
262 auto makeNetclassRules =
263 [&](
const std::shared_ptr<NETCLASS>& nc,
bool isDefault )
265 ncName = nc->GetName();
266 ncName.Replace(
"'",
"\\'" );
268 if( nc->HasClearance() )
270 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
271 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
272 nc->GetClearanceParent()->GetHumanReadableName() );
275 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
277 netclassClearanceRules.push_back( netclassRule );
281 netclassRule->AddConstraint( constraint );
284 if( nc->HasTrackWidth() )
286 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
287 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
288 nc->GetTrackWidthParent()->GetHumanReadableName() );
291 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
293 netclassClearanceRules.push_back( netclassRule );
298 netclassRule->AddConstraint( constraint );
301 if( nc->HasDiffPairWidth() )
303 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
304 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
305 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
308 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.inDiffPair('*')" ), ncName );
310 netclassItemSpecificRules.push_back( netclassRule );
314 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
315 netclassRule->AddConstraint( constraint );
318 if( nc->HasDiffPairGap() )
320 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
321 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
322 nc->GetDiffPairGapParent()->GetHumanReadableName() );
325 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s')" ), ncName );
327 netclassItemSpecificRules.push_back( netclassRule );
332 netclassRule->AddConstraint( constraint );
335 if( nc->GetDiffPairGap() < nc->GetClearance() )
337 netclassRule = std::make_shared<DRC_RULE>();
338 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (diff pair)" ),
339 nc->GetDiffPairGapParent()->GetHumanReadableName() );
342 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && AB.isCoupledDiffPair()" ), ncName );
344 netclassItemSpecificRules.push_back( netclassRule );
347 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
348 netclassRule->AddConstraint( min_clearanceConstraint );
352 if( nc->HasViaDiameter() )
354 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
355 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
356 nc->GetViaDiameterParent()->GetHumanReadableName() );
359 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
361 netclassItemSpecificRules.push_back( netclassRule );
366 netclassRule->AddConstraint( constraint );
369 if( nc->HasViaDrill() )
371 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
372 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s'" ),
373 nc->GetViaDrillParent()->GetHumanReadableName() );
376 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type != 'Micro'" ), ncName );
378 netclassItemSpecificRules.push_back( netclassRule );
383 netclassRule->AddConstraint( constraint );
386 if( nc->HasuViaDiameter() )
388 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
389 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
390 nc->GetuViaDiameterParent()->GetHumanReadableName() );
393 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
395 netclassItemSpecificRules.push_back( netclassRule );
399 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
400 netclassRule->AddConstraint( constraint );
403 if( nc->HasuViaDrill() )
405 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
406 netclassRule->m_Name = wxString::Format(
_(
"netclass '%s' (uvia)" ),
407 nc->GetuViaDrillParent()->GetHumanReadableName() );
410 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Via_Type == 'Micro'" ), ncName );
412 netclassItemSpecificRules.push_back( netclassRule );
417 netclassRule->AddConstraint( constraint );
421 m_board->SynchronizeNetsAndNetClasses(
false );
425 makeNetclassRules( netclass,
false );
428 makeNetclassRules( netclass,
false );
435 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
436 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
438 return lhs->m_Constraints[0].m_Value.Min()
439 < rhs->m_Constraints[0].m_Value.Min();
442 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
445 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
449 auto addTuningSingleRule =
451 const wxString& aNetclassName )
456 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
458 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
461 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s'" ),
470 tuningRule->AddConstraint( constraint );
475 auto addTuningDifferentialRules =
482 std::shared_ptr<DRC_RULE> tuningRule = std::make_shared<DRC_RULE>();
484 tuningRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
487 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
488 aNetclass->GetName(),
496 tuningRule->AddConstraint( constraint );
500 std::shared_ptr<DRC_RULE> tuningRule2 = std::make_shared<DRC_RULE>();
502 tuningRule2->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
505 expr2 = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
506 aNetclass->GetName(),
514 tuningRule2->AddConstraint( constraint2 );
521 std::shared_ptr<DRC_RULE> diffPairClearanceRule = std::make_shared<DRC_RULE>();
523 diffPairClearanceRule->m_Name = wxString::Format(
_(
"tuning profile '%s'" ), aProfileName );
526 expr = wxString::Format( wxT(
"A.hasExactNetclass('%s') && A.Layer == '%s' && A.inDiffPair('*')" ),
527 aNetclass->GetName(),
533 diffPairClearanceRule->AddConstraint( min_clearanceConstraint );
535 addRule( diffPairClearanceRule );
541 std::shared_ptr<TUNING_PROFILES> tuningParams =
project->GetProjectFile().TuningProfileParameters();
543 auto addNetclassTuningProfileRules =
544 [&tuningParams, &addTuningSingleRule, &addTuningDifferentialRules](
NETCLASS* aNetclass )
546 if( aNetclass->HasTuningProfile() )
548 const wxString delayProfileName = aNetclass->GetTuningProfile();
549 const TUNING_PROFILE& profile = tuningParams->GetTuningProfile( delayProfileName );
557 addTuningSingleRule( entry, delayProfileName, aNetclass->GetName() );
559 addTuningDifferentialRules( entry, delayProfileName, aNetclass );
567 addNetclassTuningProfileRules( netclass.get() );
570 addNetclassTuningProfileRules( netclass.get() );
574 auto addKeepoutZoneRule =
584 wxString::Format(
_(
"keepout area of %s" ),
DescribeRef( parentFP->GetReference() ) ),
608 rule->m_ImplicitItemId = zone->
m_Uuid;
610 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsArea('%s')" ),
615 int disallowFlags = 0;
634 rule->AddConstraint( disallowConstraint );
640 addKeepoutZoneRule( zone,
nullptr );
645 for(
ZONE* zone : footprint->Zones() )
648 addKeepoutZoneRule( zone, footprint );
656 if(
m_board && aPath.FileExists() )
658 std::vector<std::shared_ptr<DRC_RULE>> rules;
660 if( FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) ) )
665 std::function<bool( wxString* )>
resolver =
666 [&]( wxString* token ) ->
bool
668 return m_board->ResolveTextVar( token, 0 );
671 while(
char* line = lineReader.
ReadLine() )
673 wxString str( line );
674 str =
m_board->ConvertCrossReferencesToKIIDs( str );
677 rulesText << str <<
'\n';
687 for( std::shared_ptr<DRC_RULE>& rule : rules )
700 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
704 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
706 condition = rule->m_Condition;
707 condition->
Compile( &error_semaphore );
712 TO_UTF8( rule->m_Condition->GetExpression() ), 0, 0 );
721 engineConstraint->
layerTest = rule->m_LayerCondition;
738 m_logReporter->Report( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
740 provider->SetDRCEngine(
this );
775 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
778 throw original_parse_error;
815 if( !cacheGenerator.
Run() )
819 m_board->GetComponentClassManager().ForceComponentClassRecalculation();
821 int timestamp =
m_board->GetTimeStamp();
826 m_logReporter->Report( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
828 if( !provider->RunTests( aUnits ) )
837 wxASSERT( timestamp ==
m_board->GetTimeStamp() );
841#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
849 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
857 pad =
static_cast<const PAD*
>( a );
859 pad =
static_cast<const PAD*
>( b );
867 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
893 const ZONE* zone =
nullptr;
894 const FOOTPRINT* parentFootprint =
nullptr;
904 pad =
static_cast<const PAD*
>( a );
906 zone =
static_cast<const ZONE*
>( a );
909 pad =
static_cast<const PAD*
>( b );
911 zone =
static_cast<const ZONE*
>( b );
914 parentFootprint =
pad->GetParentFootprint();
918 constraint.
m_Type = aConstraintType;
920 auto applyConstraint =
923 if( c->constraint.m_Value.HasMin() )
925 if( c->parentRule && c->parentRule->IsImplicit() )
931 if( c->constraint.m_Value.HasOpt() )
934 if( c->constraint.m_Value.HasMax() )
937 switch( c->constraint.m_Type )
972 && ( ( ( !ac ) ^ ( !bc ) )
975 || ( ( footprints[0] == footprints[1] )
978 && !b_is_non_copper )
985 for(
int ii = 0; ii < 2; ++ii )
988 if( !footprints[ii] || !alt_items[ii] )
991 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
993 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
995 if( it != netcodes.end() )
998 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
999 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
1001 constraint.
SetName(
_(
"net tie" ) );
1011 int override_val = 0;
1012 std::optional<int> overrideA;
1013 std::optional<int> overrideB;
1015 if( ac && !b_is_non_copper )
1018 if( bc && !a_is_non_copper )
1021 if( overrideA.has_value() || overrideB.has_value() )
1025 if( overrideA.has_value() )
1028 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1035 if( overrideB.has_value() )
1038 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
1042 if( overrideB > override_val )
1050 if( override_val < m_designSettings->m_MinClearance )
1053 msg =
_(
"board minimum" );
1056 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1062 if( override_val < m_designSettings->m_HoleClearance )
1065 msg =
_(
"board minimum hole" );
1068 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
1087 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
1098 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
1101 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
1104 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
1115 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
1118 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
1121 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
1130 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
1142 std::optional<int>
override;
1145 override =
pad->GetLocalSolderMaskMargin();
1147 override =
static_cast<const PCB_SHAPE*
>( a )->GetLocalSolderMaskMargin();
1154 REPORT( wxString::Format(
_(
"Local override on %s; solder mask expansion: %s." ),
1164 std::optional<int>
override;
1167 override =
pad->GetLocalSolderPasteMargin();
1172 REPORT( wxString::Format(
_(
"Local override on %s; solder paste absolute clearance: %s." ),
1182 std::optional<double> overrideRatio;
1185 overrideRatio =
pad->GetLocalSolderPasteMarginRatio();
1190 REPORT( wxString::Format(
_(
"Local override on %s; solder paste relative clearance: %s." ),
1199 auto testAssertion =
1202 REPORT( wxString::Format(
_(
"Checking assertion '%s'." ),
1203 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1205 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1206 REPORT(
_(
"Assertion passed." ) )
1211 auto processConstraint =
1214 bool implicit = c->parentRule && c->parentRule->IsImplicit();
1218 switch( c->constraint.m_Type )
1227 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
1232 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
1237 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
1243 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
1249 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
1255 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1261 REPORT( wxString::Format(
_(
"Checking %s solder mask expansion: %s." ),
1267 REPORT( wxString::Format(
_(
"Checking %s solder paste absolute clearance: %s." ),
1273 REPORT( wxString::Format(
_(
"Checking %s solder paste relative clearance: %s." ),
1279 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1285 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1303 switch( c->constraint.m_Type )
1306 if( c->constraint.m_Value.HasOpt() )
1308 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1312 else if( c->constraint.m_Value.HasMin() )
1314 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1322 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1328 if( c->constraint.m_Value.HasOpt() )
1330 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1334 else if( c->constraint.m_Value.HasMin() )
1336 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1343 if( c->constraint.m_Value.HasOpt() )
1345 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1349 else if( c->constraint.m_Value.HasMin() )
1351 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1361 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1367 if( c->constraint.m_Value.HasOpt() )
1369 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1373 else if( c->constraint.m_Value.HasMin() )
1375 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1383 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1389 REPORT( wxString::Format(
_(
"Checking %s." ),
1395 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1397 c->constraint.m_Value.HasMin()
1399 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1400 c->constraint.m_Value.HasOpt()
1402 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ),
1403 c->constraint.m_Value.HasMax()
1405 : wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" ) ) )
1411 REPORT( wxString::Format(
_(
"Checking %s." ),
1417 if( a_is_non_copper || b_is_non_copper )
1421 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1423 else if( a_is_non_copper )
1425 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1428 else if( b_is_non_copper )
1430 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1449 if(
via->IsMicroVia() )
1451 else if(
via->IsBlindVia() )
1453 else if(
via->IsBuriedVia() )
1475 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1483 default: mask = 0;
break;
1487 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1490 REPORT(
_(
"Keepout constraint not met." ) )
1492 REPORT(
_(
"Disallow constraint not met." ) )
1510 if( !( c->layerTest & itemLayers ).any() )
1514 REPORT(
_(
"Keepout layer(s) not matched." ) )
1516 else if( c->parentRule )
1518 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1519 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1523 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1531 || (
m_board->GetEnabledLayers() & c->layerTest ).count() == 0 )
1535 REPORT(
_(
"Constraint layer not matched." ) )
1537 else if( c->parentRule )
1539 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1540 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1544 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1551 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1554 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1560 REPORT(
_(
"Unconditional constraint applied." ) )
1564 REPORT(
_(
"Unconditional rule applied." ) )
1569 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1573 applyConstraint( c );
1583 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1584 EscapeHTML( c->condition->GetExpression() ) ) )
1587 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1593 REPORT(
_(
"Constraint applied." ) )
1597 REPORT(
_(
"Rule applied." ) )
1602 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1606 applyConstraint( c );
1610 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1611 :
_(
"Condition not satisfied; rule ignored." ) )
1618 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1621 processConstraint( rule );
1638 REPORT( wxString::Format(
_(
"Inheriting from parent: %s." ),
1642 a = parentFootprint;
1644 b = parentFootprint;
1648 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1651 processConstraint( rule );
1661 constraint.
SetName(
_(
"board setup" ) );
1668 constraint.
SetName(
_(
"board setup" ) );
1675 constraint.
SetName(
_(
"board setup" ) );
1688 bool needBlankLine =
true;
1697 needBlankLine =
false;
1700 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1721 needBlankLine =
false;
1724 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1738 if( !a_is_non_copper && !b_is_non_copper )
1743 needBlankLine =
false;
1746 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1752 constraint.
SetName(
_(
"board minimum" ) );
1762 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1768 constraint.
SetName(
_(
"board minimum" ) );
1776 if(
pad && parentFootprint )
1783 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
1788 constraint.
SetName(
_(
"footprint" ) );
1799 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
1816 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
1833 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
1863 auto testAssertion =
1866 REPORT( wxString::Format(
_(
"Checking rule assertion '%s'." ),
1867 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1869 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1872 REPORT(
_(
"Assertion passed." ) )
1877 aFailureHandler( &c->constraint );
1881 auto processConstraint =
1885 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
1889 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1890 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1893 if( !c->condition || c->condition->GetExpression().IsEmpty() )
1895 REPORT(
_(
"Unconditional rule applied." ) )
1900 REPORT( wxString::Format(
_(
"Checking rule condition '%s'." ),
1901 EscapeHTML( c->condition->GetExpression() ) ) )
1903 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1906 REPORT(
_(
"Rule applied." ) )
1911 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
1920 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1921 processConstraint( ruleset->at( ii ) );
1931 assert( error_code >= 0 && error_code <=
DRCE_LAST );
1937 int aMarkerLayer,
const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
1939 static std::mutex globalLock;
1945 std::lock_guard<std::mutex> guard( globalLock );
1951 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
1952 aItem->GetViolatingTest()->GetName(),
1953 aItem->GetErrorMessage(
false ),
1954 aItem->GetErrorCode() );
1956 DRC_RULE* rule = aItem->GetViolatingRule();
1959 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
1963 wxString violatingItemsStr = wxT(
"Violating items: " );
1965 m_logReporter->Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
2012 wxSafeYield(
nullptr,
true );
2042 int current = c->constraint.GetValue().Min();
2044 if( current > worst )
2047 aConstraint = c->constraint;
2058 std::set<int> distinctMinimums;
2063 distinctMinimums.emplace( c->constraint.GetValue().Min() );
2066 return distinctMinimums;
2072 wxString& aBaseDpName )
2077 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
2081 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
2085 else if( ch ==
'+' )
2087 aComplementNet = wxT(
"-" );
2090 else if( ch ==
'-' )
2092 aComplementNet = wxT(
"+" );
2095 else if( ch ==
'N' )
2097 aComplementNet = wxT(
"P" );
2100 else if ( ch ==
'P' )
2102 aComplementNet = wxT(
"N" );
2111 if( rv != 0 && count >= 1 )
2113 aBaseDpName = aNetName.Left( aNetName.Length() - count );
2114 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
2124 wxString
dummy, coupledNetName;
2160 if( parentFootprint && parentFootprint->
IsNetTie() )
2167 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
2169 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
2183 if(
name == prov->GetName() )
2195 std::vector<BOARD_ITEM*> matches;
2207 for(
auto& [kiid, item] :
m_board->GetItemByIdCache() )
2209 LSET itemLayers = item->GetLayerSet();
2213 if( condition.
EvaluateFor( item,
nullptr,
static_cast<int>( aConstraint ), layer,
2216 matches.push_back( item );
constexpr EDA_IU_SCALE pcbIUScale
std::set< BOARD_ITEM *, CompareByUuid > BOARD_ITEM_SET
Set of BOARD_ITEMs ordered by UUID.
#define MAXIMUM_CLEARANCE
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
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
std::map< int, SEVERITY > m_DRCSeverities
int m_MinSilkTextThickness
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
int m_ViasMinAnnularWidth
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual 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
std::shared_ptr< DRC_RULE > createImplicitRule(const wxString &name, DRC_IMPLICIT_SOURCE aImplicitSource)
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
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
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
wxString MessageTextFromUnscaledValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
UNITS_PROVIDER(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
Handle a list of polygons defining a copper zone.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
bool GetDoNotAllowVias() const
bool GetDoNotAllowPads() const
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)
@ DRCE_TUNING_PROFILE_IMPLICIT_RULES
@ 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:
@ 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.
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