50#define ERROR_LIMIT 199
51#define EXTENDED_ERROR_LIMIT 499
68 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
70 int setLevel = wxAtoi( valueStr );
72 if( level <= setLevel )
73 printf(
"%-30s:%d | %s\n", function, line, (
const char *) msg.c_str() );
80 m_designSettings ( aSettings ),
82 m_drawingSheet( nullptr ),
83 m_schematicNetlist( nullptr ),
84 m_rulesValid( false ),
85 m_reportAllTrackErrors( false ),
86 m_testFootprints( false ),
87 m_reporter( nullptr ),
88 m_progressReporter( nullptr )
116 const ZONE* zone =
static_cast<const ZONE*
>( aItem );
142 std::shared_ptr<DRC_RULE> rule = std::make_shared<DRC_RULE>();
145 rule->m_Implicit =
true;
155 ReportAux( wxString::Format( wxT(
"Building implicit rules (per-item/class overrides, etc...)" ) ) );
165 rule->AddConstraint( widthConstraint );
169 rule->AddConstraint( connectionConstraint );
173 rule->AddConstraint( drillConstraint );
177 rule->AddConstraint( annulusConstraint );
181 rule->AddConstraint( diameterConstraint );
185 rule->AddConstraint( holeToHoleConstraint );
190 rule->AddConstraint( thermalSpokeCountConstraint );
196 rule->AddConstraint( silkClearanceConstraint );
202 rule->AddConstraint( silkTextHeightConstraint );
208 rule->AddConstraint( silkTextThicknessConstraint );
213 rule->AddConstraint( holeClearanceConstraint );
218 rule->AddConstraint( edgeClearanceConstraint );
223 rule->AddConstraint( courtyardClearanceConstraint );
227 std::shared_ptr<DRC_RULE> uViaRule =
createImplicitRule(
_(
"board setup micro-via constraints" ) );
233 uViaRule->AddConstraint( uViaDrillConstraint );
237 uViaRule->AddConstraint( uViaDiameterConstraint );
241 std::vector<std::shared_ptr<DRC_RULE>> netclassClearanceRules;
242 std::vector<std::shared_ptr<DRC_RULE>> netclassItemSpecificRules;
244 auto makeNetclassRules = [&](
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(
255 _(
"netclass '%s'" ), nc->GetClearanceParent()->GetHumanReadableName() );
256 netclassRule->m_Implicit =
true;
258 expr = wxString::Format( wxT(
"A.NetClass == '%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(
271 _(
"netclass '%s'" ), 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 =
288 wxString::Format(
_(
"netclass '%s' (diff pair)" ),
289 nc->GetDiffPairWidthParent()->GetHumanReadableName() );
290 netclassRule->m_Implicit =
true;
292 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.inDiffPair('*')" ), ncName );
294 netclassItemSpecificRules.push_back( netclassRule );
298 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
299 netclassRule->AddConstraint( constraint );
302 if( nc->HasDiffPairGap() )
304 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
305 netclassRule->m_Name =
306 wxString::Format(
_(
"netclass '%s' (diff pair)" ),
307 nc->GetDiffPairGapParent()->GetHumanReadableName() );
308 netclassRule->m_Implicit =
true;
310 expr = wxString::Format( wxT(
"A.NetClass == '%s'" ), ncName );
312 netclassItemSpecificRules.push_back( netclassRule );
317 netclassRule->AddConstraint( constraint );
320 if( nc->GetDiffPairGap() < nc->GetClearance() )
322 netclassRule = std::make_shared<DRC_RULE>();
323 netclassRule->m_Name =
324 wxString::Format(
_(
"netclass '%s' (diff pair)" ),
325 nc->GetDiffPairGapParent()->GetHumanReadableName() );
326 netclassRule->m_Implicit =
true;
328 expr = wxString::Format( wxT(
"A.NetClass == '%s' && AB.isCoupledDiffPair()" ),
331 netclassItemSpecificRules.push_back( netclassRule );
334 min_clearanceConstraint.
Value().
SetMin( nc->GetDiffPairGap() );
335 netclassRule->AddConstraint( min_clearanceConstraint );
339 if( nc->HasViaDiameter() )
341 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
342 netclassRule->m_Name = wxString::Format(
343 _(
"netclass '%s'" ), nc->GetViaDiameterParent()->GetHumanReadableName() );
344 netclassRule->m_Implicit =
true;
346 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type != 'Micro'" ), ncName );
348 netclassItemSpecificRules.push_back( netclassRule );
353 netclassRule->AddConstraint( constraint );
356 if( nc->HasViaDrill() )
358 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
359 netclassRule->m_Name = wxString::Format(
360 _(
"netclass '%s'" ), nc->GetViaDrillParent()->GetHumanReadableName() );
361 netclassRule->m_Implicit =
true;
363 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type != 'Micro'" ), ncName );
365 netclassItemSpecificRules.push_back( netclassRule );
370 netclassRule->AddConstraint( constraint );
373 if( nc->HasuViaDiameter() )
375 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
376 netclassRule->m_Name =
377 wxString::Format(
_(
"netclass '%s' (uvia)" ),
378 nc->GetuViaDiameterParent()->GetHumanReadableName() );
379 netclassRule->m_Implicit =
true;
381 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type == 'Micro'" ), ncName );
383 netclassItemSpecificRules.push_back( netclassRule );
387 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
388 netclassRule->AddConstraint( constraint );
391 if( nc->HasuViaDrill() )
393 std::shared_ptr<DRC_RULE> netclassRule = std::make_shared<DRC_RULE>();
394 netclassRule->m_Name = wxString::Format(
395 _(
"netclass '%s' (uvia)" ), nc->GetuViaDrillParent()->GetHumanReadableName() );
396 netclassRule->m_Implicit =
true;
398 expr = wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type == 'Micro'" ), ncName );
400 netclassItemSpecificRules.push_back( netclassRule );
405 netclassRule->AddConstraint( constraint );
410 makeNetclassRules( bds.
m_NetSettings->GetDefaultNetclass(),
true );
413 makeNetclassRules( netclass,
false );
415 for(
const auto& [
name, netclass] : bds.
m_NetSettings->GetCompositeNetclasses() )
416 makeNetclassRules( netclass,
false );
423 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
424 [](
const std::shared_ptr<DRC_RULE>& lhs,
const std::shared_ptr<DRC_RULE>& rhs )
426 return lhs->m_Constraints[0].m_Value.Min()
427 < rhs->m_Constraints[0].m_Value.Min();
430 for( std::shared_ptr<DRC_RULE>& ncRule : netclassClearanceRules )
433 for( std::shared_ptr<DRC_RULE>& ncRule : netclassItemSpecificRules )
438 std::vector<ZONE*> keepoutZones;
443 keepoutZones.push_back( zone );
448 for(
ZONE* zone : footprint->Zones() )
451 keepoutZones.push_back( zone );
455 for(
ZONE* zone : keepoutZones )
457 wxString
name = zone->GetZoneName();
464 rule->m_ImplicitItemId = zone->m_Uuid;
466 rule->m_Condition =
new DRC_RULE_CONDITION( wxString::Format( wxT(
"A.intersectsArea('%s')" ),
467 zone->m_Uuid.AsString() ) );
469 rule->m_LayerCondition = zone->GetLayerSet();
471 int disallowFlags = 0;
473 if( zone->GetDoNotAllowTracks() )
476 if( zone->GetDoNotAllowVias() )
479 if( zone->GetDoNotAllowPads() )
482 if( zone->GetDoNotAllowCopperPour() )
485 if( zone->GetDoNotAllowFootprints() )
490 rule->AddConstraint( disallowConstraint );
493 ReportAux( wxString::Format( wxT(
"Building %d implicit netclass rules" ),
494 (
int) netclassClearanceRules.size() ) );
500 if( aPath.FileExists() )
502 std::vector<std::shared_ptr<DRC_RULE>> rules;
504 FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) );
515 for( std::shared_ptr<DRC_RULE>& rule : rules )
523 ReportAux( wxString::Format( wxT(
"Compiling Rules (%d rules): " ), (
int)
m_rules.size() ) );
525 for( std::shared_ptr<DRC_RULE>& rule :
m_rules )
529 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
531 condition = rule->m_Condition;
542 engineConstraint->
layerTest = rule->m_LayerCondition;
558 ReportAux( wxString::Format( wxT(
"Create DRC provider: '%s'" ), provider->GetName() ) );
559 provider->SetDRCEngine(
this );
592 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
595 throw original_parse_error;
632 if( !cacheGenerator.
Run() )
639 ReportAux( wxString::Format( wxT(
"Run DRC provider: '%s'" ), provider->GetName() ) );
641 if( !provider->RunTests( aUnits ) )
654#define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } }
662 REPORT( wxString::Format(
_(
"Resolved zone connection type: %s." ),
670 pad =
static_cast<const PAD*
>( a );
672 pad =
static_cast<const PAD*
>( b );
674 if(
pad &&
pad->GetAttribute() == PAD_ATTRIB::PTH )
680 REPORT( wxString::Format(
_(
"Pad is not a through hole pad; connection will be: %s." ),
708 const ZONE* zone =
nullptr;
709 const FOOTPRINT* parentFootprint =
nullptr;
716 pad =
static_cast<const PAD*
>( a );
718 zone =
static_cast<const ZONE*
>( a );
721 pad =
static_cast<const PAD*
>( b );
723 zone =
static_cast<const ZONE*
>( b );
726 parentFootprint =
pad->GetParentFootprint();
730 constraint.
m_Type = aConstraintType;
732 auto applyConstraint =
735 if( c->constraint.m_Value.HasMin() )
737 if( c->parentRule && c->parentRule->m_Implicit )
743 if( c->constraint.m_Value.HasOpt() )
746 if( c->constraint.m_Value.HasMax() )
747 constraint .m_Value.SetMax( c->constraint.m_Value.Max() );
764 && ( ( ( !ac ) ^ ( !bc ) )
767 || ( ( footprints[0] == footprints[1] )
770 && !b_is_non_copper )
777 for(
int ii = 0; ii < 2; ++ii )
780 if( !footprints[ii] || !alt_items[ii] )
783 const std::set<int>& netcodes = footprints[ii]->
GetNetTieCache( child_items[ii] );
785 auto it = netcodes.find( alt_items[ii]->GetNetCode() );
787 if( it != netcodes.end() )
790 REPORT( wxString::Format(
_(
"Net tie on %s; clearance: 0." ),
791 EscapeHTML( footprints[ii]->GetItemDescription(
this,
true ) ) ) )
793 constraint.
SetName(
_(
"net tie" ) );
803 int override_val = 0;
804 std::optional<int> overrideA;
805 std::optional<int> overrideB;
807 if( ac && !b_is_non_copper )
810 if( bc && !a_is_non_copper )
813 if( overrideA.has_value() || overrideB.has_value() )
817 if( overrideA.has_value() )
820 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
827 if( overrideB.has_value() )
830 REPORT( wxString::Format(
_(
"Local override on %s; clearance: %s." ),
834 if( overrideB > override_val )
842 if( override_val < m_designSettings->m_MinClearance )
845 msg =
_(
"board minimum" );
848 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
854 if( override_val < m_designSettings->m_HoleClearance )
857 msg =
_(
"board minimum hole" );
860 REPORT( wxString::Format(
_(
"Board minimum hole clearance: %s." ),
873 if(
pad &&
pad->GetLocalZoneConnection() != ZONE_CONNECTION::INHERITED )
879 REPORT( wxString::Format(
_(
"Local override on %s; zone connection: %s." ),
890 if(
pad &&
pad->GetLocalThermalGapOverride(
nullptr ) > 0 )
893 int gap_override =
pad->GetLocalThermalGapOverride( &msg );
896 REPORT( wxString::Format(
_(
"Local override on %s; thermal relief gap: %s." ),
907 if(
pad &&
pad->GetLocalSpokeWidthOverride(
nullptr ) > 0 )
910 int spoke_override =
pad->GetLocalSpokeWidthOverride( &msg );
913 REPORT( wxString::Format(
_(
"Local override on %s; thermal spoke width: %s." ),
922 REPORT( wxString::Format(
_(
"%s min thickness: %s." ),
936 REPORT( wxString::Format(
_(
"Checking assertion \"%s\"." ),
937 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
939 if( c->constraint.m_Test->EvaluateFor( a, b, c->constraint.m_Type, aLayer,
942 REPORT(
_(
"Assertion passed." ) )
950 auto processConstraint =
953 bool implicit = c->parentRule && c->parentRule->m_Implicit;
957 switch( c->constraint.m_Type )
966 REPORT( wxString::Format(
_(
"Checking %s clearance: %s." ),
971 REPORT( wxString::Format(
_(
"Checking %s creepage: %s." ),
976 REPORT( wxString::Format(
_(
"Checking %s max uncoupled length: %s." ),
982 REPORT( wxString::Format(
_(
"Checking %s max skew: %s." ),
988 REPORT( wxString::Format(
_(
"Checking %s gap: %s." ),
994 REPORT( wxString::Format(
_(
"Checking %s thermal spoke width: %s." ),
1000 REPORT( wxString::Format(
_(
"Checking %s min spoke count: %s." ),
1003 c->constraint.m_Value.Min() ) ) )
1007 REPORT( wxString::Format(
_(
"Checking %s zone connection: %s." ),
1025 wxString min = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1026 wxString opt = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1027 wxString max = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
1034 switch( c->constraint.m_Type )
1037 if( c->constraint.m_Value.HasOpt() )
1039 REPORT( wxString::Format(
_(
"Checking %s track width: opt %s." ),
1043 else if( c->constraint.m_Value.HasMin() )
1045 REPORT( wxString::Format(
_(
"Checking %s track width: min %s." ),
1053 REPORT( wxString::Format(
_(
"Checking %s annular width: min %s." ),
1059 if( c->constraint.m_Value.HasOpt() )
1061 REPORT( wxString::Format(
_(
"Checking %s via diameter: opt %s." ),
1065 else if( c->constraint.m_Value.HasMin() )
1067 REPORT( wxString::Format(
_(
"Checking %s via diameter: min %s." ),
1074 if( c->constraint.m_Value.HasOpt() )
1076 REPORT( wxString::Format(
_(
"Checking %s hole size: opt %s." ),
1080 else if( c->constraint.m_Value.HasMin() )
1082 REPORT( wxString::Format(
_(
"Checking %s hole size: min %s." ),
1092 REPORT( wxString::Format(
_(
"Checking %s: min %s." ),
1098 if( c->constraint.m_Value.HasOpt() )
1100 REPORT( wxString::Format(
_(
"Checking %s diff pair gap: opt %s." ),
1104 else if( c->constraint.m_Value.HasMin() )
1106 REPORT( wxString::Format(
_(
"Checking %s clearance: min %s." ),
1114 REPORT( wxString::Format(
_(
"Checking %s hole to hole: min %s." ),
1120 REPORT( wxString::Format(
_(
"Checking %s." ),
1126 if( c->constraint.m_Value.HasMin() )
1129 if( c->constraint.m_Value.HasOpt() )
1132 if( c->constraint.m_Value.HasMax() )
1135 REPORT( wxString::Format(
_(
"Checking %s: min %s; opt %s; max %s." ),
1146 REPORT( wxString::Format(
_(
"Checking %s." ),
1152 if( a_is_non_copper || b_is_non_copper )
1156 REPORT(
_(
"Netclass clearances apply only between copper items." ) )
1158 else if( a_is_non_copper )
1160 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1163 else if( b_is_non_copper )
1165 REPORT( wxString::Format(
_(
"%s contains no copper. Rule ignored." ),
1184 switch(
static_cast<const PCB_VIA*
>( a )->GetViaType() )
1207 if(
static_cast<const ZONE*
>( a )->IsTeardropArea() )
1215 default: mask = 0;
break;
1219 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
1222 REPORT(
_(
"Keepout constraint not met." ) )
1224 REPORT(
_(
"Disallow constraint not met." ) )
1242 if( !( c->layerTest & itemLayers ).any() )
1246 REPORT(
_(
"Keepout layer(s) not matched." ) )
1248 else if( c->parentRule )
1250 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1251 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1255 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1267 REPORT(
_(
"Constraint layer not matched." ) )
1269 else if( c->parentRule )
1271 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1272 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1276 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1283 REPORT( wxString::Format(
_(
"%s is not a drilled hole; rule ignored." ),
1286 else if( !c->condition || c->condition->GetExpression().IsEmpty() )
1292 REPORT(
_(
"Unconditional constraint applied." ) )
1296 REPORT(
_(
"Unconditional rule applied." ) )
1301 REPORT(
_(
"Unconditional rule applied; overrides previous constraints." ) )
1305 applyConstraint( c );
1315 REPORT( wxString::Format(
_(
"Checking rule condition \"%s\"." ),
1316 EscapeHTML( c->condition->GetExpression() ) ) )
1319 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1325 REPORT(
_(
"Constraint applied." ) )
1329 REPORT(
_(
"Rule applied." ) )
1334 REPORT(
_(
"Rule applied; overrides previous constraints." ) )
1338 applyConstraint( c );
1342 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1343 :
_(
"Condition not satisfied; rule ignored." ) )
1350 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1352 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1353 processConstraint( ruleset->at( ii ) );
1368 a = parentFootprint;
1370 b = parentFootprint;
1374 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1376 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1377 processConstraint( ruleset->at( ii ) );
1391 bool needBlankLine =
true;
1400 needBlankLine =
false;
1403 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1424 needBlankLine =
false;
1427 REPORT( wxString::Format(
_(
"Local clearance on %s: %s." ),
1441 if( !a_is_non_copper && !b_is_non_copper )
1446 needBlankLine =
false;
1449 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1452 if( clearance < m_designSettings->m_MinClearance )
1455 constraint.
SetName(
_(
"board minimum" ) );
1465 REPORT( wxString::Format(
_(
"Board minimum clearance: %s." ),
1471 constraint.
SetName(
_(
"board minimum" ) );
1479 if(
pad && parentFootprint )
1483 if( local != ZONE_CONNECTION::INHERITED )
1486 REPORT( wxString::Format(
_(
"%s zone connection: %s." ),
1491 constraint.
SetName(
_(
"footprint" ) );
1502 REPORT( wxString::Format(
_(
"%s pad connection: %s." ),
1519 REPORT( wxString::Format(
_(
"%s thermal relief gap: %s." ),
1536 REPORT( wxString::Format(
_(
"%s thermal spoke width: %s." ),
1566 auto testAssertion =
1569 REPORT( wxString::Format(
_(
"Checking rule assertion \"%s\"." ),
1570 EscapeHTML( c->constraint.m_Test->GetExpression() ) ) )
1572 if( c->constraint.m_Test->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1575 REPORT(
_(
"Assertion passed." ) )
1580 aFailureHandler( &c->constraint );
1584 auto processConstraint =
1588 REPORT( wxString::Format(
_(
"Checking %s." ), c->constraint.GetName() ) )
1592 REPORT( wxString::Format(
_(
"Rule layer '%s' not matched; rule ignored." ),
1593 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1596 if( !c->condition || c->condition->GetExpression().IsEmpty() )
1598 REPORT(
_(
"Unconditional rule applied." ) )
1603 REPORT( wxString::Format(
_(
"Checking rule condition \"%s\"." ),
1604 EscapeHTML( c->condition->GetExpression() ) ) )
1606 if( c->condition->EvaluateFor( a,
nullptr, c->constraint.m_Type,
1609 REPORT(
_(
"Rule applied." ) )
1614 REPORT(
_(
"Condition not satisfied; rule ignored." ) )
1623 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1624 processConstraint( ruleset->at( ii ) );
1634 assert( error_code >= 0 && error_code <=
DRCE_LAST );
1642 static std::mutex globalLock;
1648 std::lock_guard<std::mutex> guard( globalLock );
1654 wxString msg = wxString::Format( wxT(
"Test '%s': %s (code %d)" ),
1655 aItem->GetViolatingTest()->GetName(),
1656 aItem->GetErrorMessage(),
1657 aItem->GetErrorCode() );
1659 DRC_RULE* rule = aItem->GetViolatingRule();
1662 msg += wxString::Format( wxT(
", violating rule: '%s'" ), rule->
m_Name );
1666 wxString violatingItemsStr = wxT(
"Violating items: " );
1668 m_reporter->
Report( wxString::Format( wxT(
" |- violating position (%d, %d)" ),
1724 wxSafeYield(
nullptr,
true );
1753 int current = c->constraint.GetValue().Min();
1755 if( current > worst )
1758 aConstraint = c->constraint;
1769 std::set<int> distinctMinimums;
1774 distinctMinimums.emplace( c->constraint.GetValue().Min() );
1777 return distinctMinimums;
1783 wxString& aBaseDpName )
1788 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
1792 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
1796 else if( ch ==
'+' )
1798 aComplementNet = wxT(
"-" );
1801 else if( ch ==
'-' )
1803 aComplementNet = wxT(
"+" );
1806 else if( ch ==
'N' )
1808 aComplementNet = wxT(
"P" );
1811 else if ( ch ==
'P' )
1813 aComplementNet = wxT(
"N" );
1822 if( rv != 0 && count >= 1 )
1824 aBaseDpName = aNetName.Left( aNetName.Length() - count );
1825 aComplementNet = wxString( aBaseDpName ) << aComplementNet << aNetName.Right( count - 1 );
1835 wxString
dummy, coupledNetName;
1871 if( parentFootprint && parentFootprint->
IsNetTie() )
1878 if( padToNetTieGroupMap[
pad->GetNumber() ] >= 0 && aTrackNetCode ==
pad->GetNetCode() )
1880 if(
pad->GetEffectiveShape( aTrackLayer )->Collide( aCollisionPos,
epsilon ) )
1894 if(
name == prov->GetName() )
constexpr EDA_IU_SCALE pcbIUScale
constexpr EDA_IU_SCALE unityScale
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 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.
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
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
BOARD_DESIGN_SETTINGS & GetDesignSettings() 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)
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)
void ReportAux(const wxString &aStr)
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
LSET is a set of PCB_LAYER_IDs.
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
static 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
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).
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
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 GetDoNotAllowCopperPour() const
bool HasKeepoutParametersSet() const
Accessor to determine if any keepout parameters are set.
int GetThermalReliefGap() const
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
@ PHYSICAL_CLEARANCE_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
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.