49 if( wxGetEnv( wxT(
"DRC_DEBUG" ), &valueStr ) )
51 int setLevel = wxAtoi( valueStr );
53 if( level <= setLevel )
54 printf(
"%-30s:%d | %s\n",
function, line, (
const char *) msg.c_str() );
60 m_designSettings ( aSettings ),
62 m_drawingSheet( nullptr ),
63 m_schematicNetlist( nullptr ),
64 m_rulesValid( false ),
66 m_reportAllTrackErrors( false ),
67 m_testFootprints( false ),
68 m_reporter( nullptr ),
69 m_progressReporter( nullptr )
101 const ZONE* zone = static_cast<const ZONE*>( aItem );
228 std::vector<DRC_RULE*> netclassClearanceRules;
229 std::vector<DRC_RULE*> netclassItemSpecificRules;
231 auto makeNetclassRules =
232 [&](
const NETCLASSPTR& nc,
bool isDefault )
234 wxString ncName = nc->GetName();
239 if( nc->GetClearance() || nc->GetTrackWidth() )
247 netclassClearanceRules.push_back( netclassRule );
249 if( nc->GetClearance() )
253 nc->GetClearance() ) );
257 if( nc->GetTrackWidth() )
266 if( nc->GetDiffPairWidth() )
276 netclassItemSpecificRules.push_back( netclassRule );
280 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
284 if( nc->GetDiffPairGap() )
293 netclassItemSpecificRules.push_back( netclassRule );
302 if( nc->GetDiffPairGap() < nc->GetClearance() )
309 expr =
wxString::Format( wxT(
"A.NetClass == '%s' && AB.isCoupledDiffPair()" ),
312 netclassItemSpecificRules.push_back( netclassRule );
316 nc->GetDiffPairGap() ) );
321 if( nc->GetViaDiameter() || nc->GetViaDrill() )
327 expr =
wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type != 'Micro'" ),
330 netclassItemSpecificRules.push_back( netclassRule );
332 if( nc->GetViaDiameter() )
340 if( nc->GetViaDrill() )
349 if( nc->GetuViaDiameter() || nc->GetuViaDrill() )
355 expr =
wxString::Format( wxT(
"A.NetClass == '%s' && A.Via_Type == 'Micro'" ),
358 netclassItemSpecificRules.push_back( netclassRule );
360 if( nc->GetuViaDiameter() )
364 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
368 if( nc->GetuViaDrill() )
381 for(
const std::pair<const wxString, NETCLASSPTR>& netclass : bds.
GetNetClasses() )
382 makeNetclassRules( netclass.second,
false );
389 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
393 < rhs->m_Constraints[0].m_Value.Min();
396 for(
DRC_RULE* ncRule : netclassClearanceRules )
399 for(
DRC_RULE* ncRule : netclassItemSpecificRules )
404 std::vector<ZONE*> keepoutZones;
409 keepoutZones.push_back( zone );
414 for(
ZONE* zone : footprint->Zones() )
417 keepoutZones.push_back( zone );
421 for(
ZONE* zone : keepoutZones )
423 wxString
name = zone->GetZoneName();
431 zone->m_Uuid.AsString() ) );
435 int disallowFlags = 0;
437 if( zone->GetDoNotAllowTracks() )
440 if( zone->GetDoNotAllowVias() )
443 if( zone->GetDoNotAllowPads() )
446 if( zone->GetDoNotAllowCopperPour() )
449 if( zone->GetDoNotAllowFootprints() )
458 (
int) netclassClearanceRules.size() ) );
475 const auto value = c.GetValue();
477 if ( value.HasMin() )
480 if ( value.HasOpt() )
483 if ( value.HasMax() )
489 std::vector<FORMATTER> formats =
507 for( FORMATTER& fmt : formats )
509 if( fmt.type == constraint.
m_Type )
511 wxString rv = fmt.name + wxS(
" " );
514 rv += fmt.formatter( constraint );
526 if( aPath.FileExists() )
528 std::vector<DRC_RULE*> rules;
530 FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) );
555 drc_dbg( 7, wxT(
"do prov %s" ), provider->GetName() );
559 drc_dbg( 7, wxT(
"do id %d" ),
id );
567 bool compileOk =
false;
568 std::vector<DRC_CONSTRAINT> matchingConstraints;
569 drc_dbg( 7, wxT(
"Scan provider %s, rule %s" ), provider->GetName(), rule->m_Name );
571 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
573 condition = rule->m_Condition;
574 compileOk = condition->
Compile(
nullptr, 0, 0 );
579 drc_dbg(7, wxT(
"scan constraint id %d\n" ), constraint.
m_Type );
581 if( constraint.
m_Type !=
id )
586 rcons->
layerTest = rule->m_LayerCondition;
589 matchingConstraints.push_back( constraint );
596 if( !matchingConstraints.empty() )
605 compileOk ? wxT(
"OK" ) : wxT(
"ERROR" ) ) );
627 provider->SetDRCEngine(
this );
663 wxFAIL_MSG( wxT(
"Compiling implicit rules failed." ) );
666 throw original_parse_error;
693 if( !
ReportPhase(
_(
"Tessellating copper zones..." ) ) )
698 std::vector<ZONE*> copperZones;
702 zone->CacheBoundingBox();
703 zone->CacheTriangulation();
705 if( !zone->GetIsRuleArea() )
706 copperZones.push_back( zone );
711 for(
ZONE* zone : footprint->Zones() )
713 zone->CacheBoundingBox();
714 zone->CacheTriangulation();
716 if( !zone->GetIsRuleArea() )
717 copperZones.push_back( zone );
720 footprint->BuildPolyCourtyards();
723 int zoneCount = copperZones.size();
725 for(
int ii = 0; ii < zoneCount; ++ii )
727 ZONE* zone = copperZones[ ii ];
729 if( ( ii %
delta ) == 0 || ii == zoneCount - 1 )
746 if( !provider->IsEnabled() )
749 drc_dbg( 0, wxT(
"Running test provider: '%s'\n" ), provider->GetName() );
753 if( !provider->Run() )
763 #define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } } 764 #define UNITS aReporter ? aReporter->GetUnits() : EDA_UNITS::MILLIMETRES 765 #define REPORT_VALUE( v ) MessageTextFromValue( UNITS, v ) 772 static_cast<const BOARD_CONNECTED_ITEM*>( a ) :
nullptr;
774 static_cast<const BOARD_CONNECTED_ITEM*>( b ) :
nullptr;
780 constraint.
m_Type = aConstraintType;
787 if( ac && !b_is_non_copper )
802 if( bc && !a_is_non_copper )
813 if( overrideB >
override )
822 if( override < m_designSettings->m_MinClearance )
825 m_msg =
_(
"board minimum" );
834 if( override < m_designSettings->m_HoleClearance )
837 m_msg =
_(
"board minimum hole" );
845 constraint.SetName(
m_msg );
846 constraint.m_Value.SetMin(
override );
851 auto processConstraint =
854 bool implicit = c->parentRule && c->parentRule->m_Implicit;
858 switch( c->constraint.m_Type )
866 int val = c->constraint.m_Value.Min();
879 wxString min = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
880 wxString opt = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
881 wxString max = wxT(
"<i>" ) +
_(
"undefined" ) + wxT(
"</i>" );
888 switch( c->constraint.m_Type )
893 default: msg =
_(
"constraint" );
break;
903 if( c->constraint.m_Value.HasMin() )
906 if( c->constraint.m_Value.HasOpt() )
909 if( c->constraint.m_Value.HasMax() )
929 if( implicit && ( a_is_non_copper || b_is_non_copper ) )
931 REPORT(
_(
"Board and netclass clearances apply only between copper " 948 switch( static_cast<const PCB_VIA*>( a )->GetViaType() )
970 default: mask = 0;
break;
974 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
977 REPORT(
_(
"Keepout constraint not met." ) )
979 REPORT(
_(
"Disallow constraint not met." ) )
988 const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( a );
997 if( !( c->layerTest & itemLayers ).any() )
1001 REPORT(
_(
"Keepout layer(s) not matched." ) )
1003 else if( c->parentRule )
1007 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1011 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1023 REPORT(
"Constraint layer not matched." )
1025 else if( c->parentRule )
1028 EscapeHTML( c->parentRule->m_LayerSource ) ) )
1032 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
1038 if( !c->condition || c->condition->GetExpression().IsEmpty() )
1040 REPORT( implicit ?
_(
"Unconditional constraint applied." )
1041 :
_(
"Unconditional rule applied." ) );
1043 constraint = c->constraint;
1055 EscapeHTML( c->condition->GetExpression() ) ) )
1058 if( c->condition->EvaluateFor( a, b, c->constraint.m_Type, aLayer, aReporter ) )
1060 REPORT( implicit ?
_(
"Constraint applied." )
1061 :
_(
"Rule applied; overrides previous constraints." ) )
1063 if( c->constraint.m_Value.HasMin() )
1064 constraint.m_Value.SetMin( c->constraint.m_Value.Min() );
1066 if( c->constraint.m_Value.HasOpt() )
1067 constraint.m_Value.SetOpt( c->constraint.m_Value.Opt() );
1069 if( c->constraint.m_Value.HasMax() )
1070 constraint .m_Value.SetMax( c->constraint.m_Value.Max() );
1075 constraint.m_DisallowFlags = c->constraint.m_DisallowFlags;
1077 constraint.SetParentRule( c->constraint.GetParentRule() );
1083 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
1084 :
_(
"Condition not satisfied; rule ignored." ) )
1093 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintType ];
1095 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
1096 processConstraint( ruleset->at( ii ) );
1099 if( constraint.GetParentRule() && !constraint.GetParentRule()->m_Implicit )
1107 int global = constraint.m_Value.Min();
1110 int clearance = global;
1119 if( localA > clearance )
1130 if( localB > clearance )
1134 if( localA > global || localB > global )
1136 constraint.SetParentRule(
nullptr );
1137 constraint.SetName(
m_msg );
1138 constraint.m_Value.SetMin( clearance );
1143 if( !constraint.GetParentRule() )
1146 constraint.m_DisallowFlags = 0;
1159 assert( error_code >= 0 && error_code <=
DRCE_LAST );
1174 aItem->GetViolatingTest()->GetName(),
1175 aItem->GetErrorMessage(),
1176 aItem->GetErrorCode() );
1178 DRC_RULE* rule = aItem->GetViolatingRule();
1185 wxString violatingItemsStr = wxT(
"Violating items: " );
1241 int current = c->constraint.GetValue().Min();
1243 if( current > worst )
1246 aConstraint = c->constraint;
1257 wxString& aBaseDpName )
1262 for(
auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
1266 if( ( ch >=
'0' && ch <=
'9' ) || ch ==
'_' )
1270 else if( ch ==
'+' )
1272 aComplementNet = wxT(
"-" );
1275 else if( ch ==
'-' )
1277 aComplementNet = wxT(
"+" );
1280 else if( ch ==
'N' )
1282 aComplementNet = wxT(
"P" );
1285 else if ( ch ==
'P' )
1287 aComplementNet = wxT(
"N" );
1296 if( rv != 0 && count >= 1 )
1298 aBaseDpName = aNetName.Left( aNetName.Length() - count );
1299 aComplementNet = aBaseDpName + aComplementNet + aNetName.Right( count - 1 );
1309 wxString
dummy, coupledNetName;
1338 if( aItem->
Type() ==
PCB_PAD_T && !static_cast<PAD*>( aItem )->FlashLayer( aLayer ) )
1340 PAD* aPad = static_cast<PAD*>( aItem );
1350 return std::make_shared<SHAPE_SEGMENT>( *hole );
1353 return std::make_shared<SHAPE_NULL>();
1373 if(
name == prov->GetName() )
DRC_TEST_PROVIDER * GetTestProvider(const wxString &name) const
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
void loadRules(const wxFileName &aPath)
Load and parse a rule set from an sexpr text file.
class FP_TEXT, text in a footprint
bool GetDoNotAllowFootprints() const
std::vector< int > m_errorLimits
bool ReportPhase(const wxString &aMessage)
DRC_RULE_CONDITION * m_Condition
std::vector< DRC_TEST_PROVIDER * > m_testProviders
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
MINOPTMAX< int > & Value()
std::vector< DRC_TEST_PROVIDER * > GetTestProviders() const
static std::shared_ptr< SHAPE > GetShape(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
static bool IsNetADiffPair(BOARD *aBoard, NETINFO_ITEM *aNet, int &aNetP, int &aNetN)
static DRC_TEST_PROVIDER_REGISTRY & Instance()
int GetHolePlatingThickness() const
Pad & via drills are finish size.
bool GetDoNotAllowVias() const
bool IsErrorLimitExceeded(int error_code)
bool Ignore(int aDRCErrorCode)
Return true if the DRC error code's severity is SEVERITY_IGNORE.
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
DRC_CONSTRAINT constraint
class PCB_TEXT, text on a layer
class PCB_ARC, an arc track segment on a copper layer
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
class FP_SHAPE, a footprint edge
class PAD, a pad in a footprint
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
virtual int GetLocalClearanceOverrides(wxString *aSource) const
Return any local clearance overrides set in the "classic" (ie: pre-rule) system.
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.
A pure virtual class used to derive REPORTER objects from.
static bool IsNetTie(BOARD_ITEM *aItem)
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
class PCB_TRACK, a track segment (segment on a copper layer)
DRC_RULE_CONDITION * condition
BOARD_DESIGN_SETTINGS * m_designSettings
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
bool HasRulesForConstraintType(DRC_CONSTRAINT_T constraintID)
wxString GetExpression() const
void SynchronizeNetsAndNetClasses()
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
bool GetDoNotAllowPads() const
bool GetDoNotAllowCopperPour() const
LSET is a set of PCB_LAYER_IDs.
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint)
void addRule(DRC_RULE *rule)
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
std::vector< DRC_RULE * > m_rules
std::vector< DRC_CONSTRAINT > m_Constraints
void drcPrintDebugMessage(int level, const wxString &msg, const char *function, int line)
FOOTPRINTS & Footprints()
bool GetDoNotAllowTracks() const
void Parse(std::vector< DRC_RULE * > &aRules, REPORTER *aReporter)
bool ReportProgress(double aProgress)
const wxString & GetNetname() const
std::unordered_map< DRC_CONSTRAINT_T, std::vector< DRC_ENGINE_CONSTRAINT * > * > m_constraintMap
NETCLASSES & GetNetClasses() const
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
Handle a list of polygons defining a copper zone.
int m_ViasMinAnnularWidth
class ZONE, a copper pour area
int m_CopperEdgeClearance
PROGRESS_REPORTER * m_progressReporter
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
void IncrementTimeStamp()
static bool isKeepoutZone(const BOARD_ITEM *aItem, bool aCheckFlags)
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
static wxString formatConstraint(const DRC_CONSTRAINT &constraint)
EDA_ITEM_FLAGS GetFlags() const
class FOOTPRINT, a footprint
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
DRC_ENGINE(BOARD *aBoard=nullptr, BOARD_DESIGN_SETTINGS *aSettings=nullptr)
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out #DRC_ITEMs and po...
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
DRC_RULE * createImplicitRule(const wxString &name)
Handle the data for a net.
A filename or source description, a problem input line, a line number, a byte offset,...
Information pertinent to a Pcbnew printed circuit board.
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
void ReportAux(const wxString &aStr)
PCB_LAYER_ID
A quick note on layer IDs:
PAD_ATTRIB GetAttribute() const
virtual wxString GetSelectMenuText(EDA_UNITS aUnits) const
Return the text to display to be used in the selection clarification context menu when multiple items...
void AddConstraint(DRC_CONSTRAINT &aConstraint)
class ZONE, managed by a footprint
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints)
Run the DRC tests.
static LSET BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
DRC_VIOLATION_HANDLER m_violationHandler
bool Compile(REPORTER *aReporter, int aSourceLine=0, int aSourceOffset=0)
std::map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTrees
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
NETCLASSPTR GetDefault() const
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
class PCB_VIA, a via (like a track segment on a copper layer)
bool m_MicroViasAllowed
true to allow micro vias
#define drc_dbg(level, fmt,...)
BOARD_ITEM_CONTAINER * GetParent() const
bool m_reportAllTrackErrors
virtual int GetLocalClearance(wxString *aSource) const
Return any local clearances set in the "classic" (ie: pre-rule) system.
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const wxPoint &aPos)
class PCB_SHAPE, a segment not on copper layers
virtual bool IsOnCopperLayer() const
void InitEngine(const wxFileName &aRulePath)
Initialize the DRC engine.
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
KICAD_T Type() const
Returns the type of object.
Container for design settings for a BOARD object.
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).