44 if( wxGetEnv(
"DRC_DEBUG", &valueStr ) )
46 int setLevel = wxAtoi( valueStr );
48 if( level <= setLevel )
50 printf(
"%-30s:%d | %s\n",
function, line, (
const char *) msg.c_str() );
57 m_designSettings ( aSettings ),
59 m_drawingSheet( nullptr ),
60 m_schematicNetlist( nullptr ),
61 m_rulesValid( false ),
63 m_reportAllTrackErrors( false ),
64 m_testFootprints( false ),
65 m_reporter( nullptr ),
66 m_progressReporter( nullptr )
98 const ZONE* zone = static_cast<const ZONE*>( aItem );
223 std::vector<DRC_RULE*> netclassClearanceRules;
224 std::vector<DRC_RULE*> netclassItemSpecificRules;
226 auto makeNetclassRules =
227 [&](
const NETCLASSPTR& nc,
bool isDefault )
229 wxString ncName = nc->GetName();
234 if( nc->GetClearance() || nc->GetTrackWidth() )
243 netclassClearanceRules.push_back( netclassRule );
245 if( nc->GetClearance() )
252 if( nc->GetTrackWidth() )
261 if( nc->GetDiffPairWidth() || nc->GetDiffPairGap() )
270 netclassItemSpecificRules.push_back( netclassRule );
272 if( nc->GetDiffPairWidth() )
276 constraint.
Value().
SetOpt( nc->GetDiffPairWidth() );
280 if( nc->GetDiffPairGap() )
289 if( nc->GetViaDiameter() || nc->GetViaDrill() )
298 netclassItemSpecificRules.push_back( netclassRule );
300 if( nc->GetViaDiameter() )
308 if( nc->GetViaDrill() )
317 if( nc->GetuViaDiameter() || nc->GetuViaDrill() )
326 netclassItemSpecificRules.push_back( netclassRule );
328 if( nc->GetuViaDiameter() )
332 constraint.
Value().
SetMin( nc->GetuViaDiameter() );
336 if( nc->GetuViaDrill() )
349 for(
const std::pair<const wxString, NETCLASSPTR>& netclass : bds.
GetNetClasses() )
350 makeNetclassRules( netclass.second,
false );
357 std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
361 < rhs->m_Constraints[0].m_Value.Min();
364 for(
DRC_RULE* ncRule : netclassClearanceRules )
367 for(
DRC_RULE* ncRule : netclassItemSpecificRules )
372 std::vector<ZONE*> keepoutZones;
377 keepoutZones.push_back( zone );
382 for(
ZONE* zone : footprint->Zones() )
385 keepoutZones.push_back( zone );
389 for(
ZONE* zone : keepoutZones )
391 wxString
name = zone->GetZoneName();
396 name = zone->m_Uuid.AsString();
408 int disallowFlags = 0;
410 if( zone->GetDoNotAllowTracks() )
413 if( zone->GetDoNotAllowVias() )
416 if( zone->GetDoNotAllowPads() )
419 if( zone->GetDoNotAllowCopperPour() )
422 if( zone->GetDoNotAllowFootprints() )
431 (
int) netclassClearanceRules.size() ) );
447 const auto value = c.GetValue();
449 if ( value.HasMin() )
452 if ( value.HasOpt() )
455 if ( value.HasMax() )
461 std::vector<FORMATTER> formats =
479 for( FORMATTER& fmt : formats )
481 if( fmt.type == constraint.
m_Type )
483 wxString rv = fmt.name +
" ";
486 rv += fmt.formatter( constraint );
501 if( aPath.FileExists() )
503 std::vector<DRC_RULE*> rules;
505 FILE* fp = wxFopen( aPath.GetFullPath(), wxT(
"rt" ) );
530 drc_dbg( 7,
"do prov %s", provider->GetName() );
542 bool compileOk =
false;
543 std::vector<DRC_CONSTRAINT> matchingConstraints;
544 drc_dbg( 7,
"Scan provider %s, rule %s", provider->GetName(), rule->m_Name );
546 if( rule->m_Condition && !rule->m_Condition->GetExpression().IsEmpty() )
548 condition = rule->m_Condition;
549 compileOk = condition->
Compile(
nullptr, 0, 0 );
556 if( constraint.
m_Type !=
id )
561 rcons->
layerTest = rule->m_LayerCondition;
564 matchingConstraints.push_back( constraint );
571 if( !matchingConstraints.empty() )
580 compileOk ?
"OK" :
"ERROR" ) );
605 provider->SetDRCEngine(
this );
639 wxFAIL_MSG(
"Compiling implict rules failed." );
642 throw original_parse_error;
670 if( !
ReportPhase(
_(
"Tessellating copper zones..." ) ) )
675 std::vector<ZONE*> copperZones;
679 zone->CacheBoundingBox();
680 zone->CacheTriangulation();
682 if( !zone->GetIsRuleArea() )
683 copperZones.push_back( zone );
688 for(
ZONE* zone : footprint->Zones() )
690 zone->CacheBoundingBox();
691 zone->CacheTriangulation();
693 if( !zone->GetIsRuleArea() )
694 copperZones.push_back( zone );
697 footprint->BuildPolyCourtyards();
700 int zoneCount = copperZones.size();
702 for(
int ii = 0; ii < zoneCount; ++ii )
704 ZONE* zone = copperZones[ ii ];
706 if( ( ii % delta ) == 0 || ii == zoneCount - 1 )
723 if( !provider->IsEnabled() )
726 drc_dbg( 0,
"Running test provider: '%s'\n", provider->GetName() );
730 if( !provider->Run() )
740 #define REPORT( s ) { if( aReporter ) { aReporter->Report( s ); } } 741 #define UNITS aReporter ? aReporter->GetUnits() : EDA_UNITS::MILLIMETRES 748 static_cast<const BOARD_CONNECTED_ITEM*>( a ) :
nullptr;
750 static_cast<const BOARD_CONNECTED_ITEM*>( b ) :
nullptr;
756 bool implicit =
false;
784 if( overrideA || overrideB )
787 constraint.
m_Value.
SetMin( std::max( overrideA, overrideB ) );
792 auto processConstraint =
795 implicit = c->parentRule && c->parentRule->m_Implicit;
801 int val = c->constraint.m_Value.Min();
808 int val = c->constraint.m_Value.Min();
815 int val = c->constraint.m_Value.Min();
822 int val = c->constraint.m_Value.Min();
829 int val = c->constraint.m_Value.Min();
841 if( implicit && ( a_is_non_copper || b_is_non_copper ) )
843 REPORT(
_(
"Board and netclass clearances apply only between copper " 880 default: mask = 0;
break;
884 if( ( c->constraint.m_DisallowFlags & mask ) == 0 )
887 REPORT(
_(
"Keepout constraint not met." ) )
889 REPORT(
_(
"Disallow constraint not met." ) )
898 const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( a );
907 if( !( c->layerTest & itemLayers ).any() )
911 REPORT(
_(
"Keepout layer(s) not matched." ) )
913 else if( c->parentRule )
917 EscapeHTML( c->parentRule->m_LayerSource ) ) )
921 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
932 REPORT(
"Constraint layer not matched." )
934 else if( c->parentRule )
937 EscapeHTML( c->parentRule->m_LayerSource ) ) )
941 REPORT(
_(
"Rule layer not matched; rule ignored." ) )
947 if( !c->condition || c->condition->GetExpression().IsEmpty() )
949 REPORT( implicit ?
_(
"Unconditional constraint applied." )
950 :
_(
"Unconditional rule applied." ) );
952 constraintRef = &c->constraint;
964 EscapeHTML( c->condition->GetExpression() ) ) )
967 if( c->condition->EvaluateFor( a, b, aLayer, aReporter ) )
969 REPORT( implicit ?
_(
"Constraint applied." )
970 :
_(
"Rule applied; overrides previous constraints." ) )
972 constraintRef = &c->constraint;
977 REPORT( implicit ?
_(
"Membership not satisfied; constraint ignored." )
978 :
_(
"Condition not satisfied; rule ignored." ) )
987 std::vector<DRC_ENGINE_CONSTRAINT*>* ruleset =
m_constraintMap[ aConstraintId ];
992 for(
int ii = 0; ii < (int) ruleset->size(); ++ii )
994 processConstraint( ruleset->at( ii ) );
1000 for(
int ii = (
int) ruleset->size() - 1; ii >= 0; --ii )
1002 if( processConstraint( ruleset->at( ii ) ) )
1008 bool explicitConstraintFound = constraintRef && !implicit;
1015 int global = constraintRef ? constraintRef->m_Value.Min() : 0;
1018 int clearance = global;
1027 if( localA > clearance )
1038 if( localB > clearance )
1042 if( localA > global || localB > global )
1053 return constraintRef ? *constraintRef : nullConstraint;
1062 assert( error_code >= 0 && error_code <=
DRCE_LAST );
1077 aItem->GetViolatingTest()->GetName(),
1078 aItem->GetErrorMessage(),
1079 aItem->GetErrorCode() );
1081 DRC_RULE* rule = aItem->GetViolatingRule();
1088 wxString violatingItemsStr =
"Violating items: ";
1143 int current = c->constraint.GetValue().Min();
1145 if( current > worst )
1148 aConstraint = c->constraint;
1159 wxString& aBaseDpName )
1163 if( aNetName.EndsWith(
"+" ) )
1165 aComplementNet =
"-";
1168 else if( aNetName.EndsWith(
"P" ) )
1170 aComplementNet =
"N";
1173 else if( aNetName.EndsWith(
"-" ) )
1175 aComplementNet =
"+";
1178 else if( aNetName.EndsWith(
"N" ) )
1180 aComplementNet =
"P";
1184 else if( aNetName.Right( 2 ).IsNumber() && aNetName.Right( 3 ).Left( 1 ) ==
"P" )
1186 aComplementNet =
"N" + aNetName.Right( 2 );
1190 else if( aNetName.Right( 1 ).IsNumber() && aNetName.Right( 2 ).Left( 1 ) ==
"P" )
1192 aComplementNet =
"N" + aNetName.Right( 1 );
1196 else if( aNetName.Right( 2 ).IsNumber() && aNetName.Right( 3 ).Left( 1 ) ==
"N" )
1198 aComplementNet =
"P" + aNetName.Right( 2 );
1202 else if( aNetName.Right( 1 ).IsNumber() && aNetName.Right( 2 ).Left( 1 ) ==
"N" )
1204 aComplementNet =
"P" + aNetName.Right( 1 );
1209 aBaseDpName = aNetName.Left( aNetName.Length() - aComplementNet.Length() );
1210 aComplementNet = aBaseDpName + aComplementNet;
1220 wxString
dummy, coupledNetName;
1249 if( aItem->
Type() ==
PCB_PAD_T && !static_cast<PAD*>( aItem )->FlashLayer( aLayer ) )
1251 PAD* aPad = static_cast<PAD*>( aItem );
1261 return std::make_shared<SHAPE_SEGMENT>( *hole );
1264 return std::make_shared<SHAPE_NULL>();
1283 if(
name == prov->GetName() )
DRC_TEST_PROVIDER * GetTestProvider(const wxString &name) const
virtual void AdvancePhase()
Uses the next vailable virtual zone of the dialog progress bar.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
void loadRules(const wxFileName &aPath)
Loads and parses 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 ARC, an arc track segment on a copper layer
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
class FP_SHAPE, a footprint edge
class PAD, a pad in a footprint
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)
Checks 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,...
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.
class TRACK, a track segment (segment on a copper layer)
DRC_RULE_CONDITION * condition
BOARD_DESIGN_SETTINGS * m_designSettings
PAD_ATTR_T GetAttribute() const
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
virtual void SetCurrentProgress(double aProgress)
Set the progress value to aProgress (0..1)
PCB_LAYER_ID
A quick note on layer IDs:
bool GetDoNotAllowCopperPour() const
LSET is a set of PCB_LAYER_IDs.
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint)
void addRule(DRC_RULE *rule)
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()
virtual BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
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
ZONE handles a list of polygons defining a copper zone.
class ZONE, a copper pour area
int m_CopperEdgeClearance
PROGRESS_REPORTER * m_progressReporter
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintId, 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)
static wxString formatConstraint(const DRC_CONSTRAINT &constraint)
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.
#define HOLE_PROXY
Indicates the BOARD_ITEM is a proxy for its hole.
DRC_ENGINE(BOARD *aBoard=nullptr, BOARD_DESIGN_SETTINGS *aSettings=nullptr)
DRC_TEST_PROVIDER is a base class that represents a DRC "provider" which runs some DRC functions over...
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)
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)
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
class ZONE, managed by a footprint
NETCLASS * GetDefault() const
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints)
Runs 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
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
NETCLASSPTR GetDefault() const
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
class VIA, a via (like a track segment on a copper layer)
bool m_MicroViasAllowed
true to allow micro vias
#define drc_dbg(level, fmt,...)
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
STATUS_FLAGS GetFlags() const
BOARD_ITEM_CONTAINER * GetParent() const
bool m_reportAllTrackErrors
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, wxPoint aPos)
virtual int GetLocalClearance(wxString *aSource) const
Return any local clearances set in the "classic" (ie: pre-rule) system.
class PCB_SHAPE, a segment not on copper layers
virtual bool IsOnCopperLayer() const
void InitEngine(const wxFileName &aRulePath)
Initializes 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.