Update DRC rules to new layer and disallow grammars.
Also adds support for hooking rules up to named zones. Fixes https://gitlab.com/kicad/code/kicad/issues/2041
This commit is contained in:
parent
406de56964
commit
e5b50d90a7
|
@ -360,9 +360,9 @@ void AR_AUTOPLACER::buildFpAreas( MODULE* aFootprint, int aFpClearance )
|
||||||
addFpBody( fpBBox.GetOrigin(), fpBBox.GetEnd(), layerMask );
|
addFpBody( fpBBox.GetOrigin(), fpBBox.GetEnd(), layerMask );
|
||||||
|
|
||||||
// Trace pads + clearance areas.
|
// Trace pads + clearance areas.
|
||||||
for( auto pad : aFootprint->Pads() )
|
for( D_PAD* pad : aFootprint->Pads() )
|
||||||
{
|
{
|
||||||
int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance();
|
int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance( pad->GetLayer() );
|
||||||
addPad( pad, margin );
|
addPad( pad, margin );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,9 +414,9 @@ void AR_AUTOPLACER::genModuleOnRoutingMatrix( MODULE* Module )
|
||||||
CELL_IS_MODULE, AR_MATRIX::WRITE_OR_CELL );
|
CELL_IS_MODULE, AR_MATRIX::WRITE_OR_CELL );
|
||||||
|
|
||||||
// Trace pads + clearance areas.
|
// Trace pads + clearance areas.
|
||||||
for( auto pad : Module->Pads() )
|
for( D_PAD* pad : Module->Pads() )
|
||||||
{
|
{
|
||||||
int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance();
|
int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance( pad->GetLayer() );
|
||||||
m_matrix.PlacePad( pad, CELL_IS_MODULE, margin, AR_MATRIX::WRITE_OR_CELL );
|
m_matrix.PlacePad( pad, CELL_IS_MODULE, margin, AR_MATRIX::WRITE_OR_CELL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,8 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetEffectiveNetclass() const
|
||||||
* LEVEL 2: Rules
|
* LEVEL 2: Rules
|
||||||
* LEVEL 3: Accumulated local settings, netclass settings, & board design settings
|
* LEVEL 3: Accumulated local settings, netclass settings, & board design settings
|
||||||
*/
|
*/
|
||||||
int BOARD_CONNECTED_ITEM::GetClearance( BOARD_ITEM* aItem, wxString* aSource ) const
|
int BOARD_CONNECTED_ITEM::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem,
|
||||||
|
wxString* aSource ) const
|
||||||
{
|
{
|
||||||
BOARD* board = GetBoard();
|
BOARD* board = GetBoard();
|
||||||
int clearance = 0;
|
int clearance = 0;
|
||||||
|
@ -122,7 +123,7 @@ int BOARD_CONNECTED_ITEM::GetClearance( BOARD_ITEM* aItem, wxString* aSource ) c
|
||||||
|
|
||||||
// LEVEL 2: Rules
|
// LEVEL 2: Rules
|
||||||
//
|
//
|
||||||
if( GetRuleClearance( aItem, &clearance, aSource ) )
|
if( GetRuleClearance( aItem, aLayer, &clearance, aSource ) )
|
||||||
return clearance;
|
return clearance;
|
||||||
|
|
||||||
// LEVEL 3: Accumulated local settings, netclass settings, & board design settings
|
// LEVEL 3: Accumulated local settings, netclass settings, & board design settings
|
||||||
|
@ -163,17 +164,18 @@ int BOARD_CONNECTED_ITEM::GetClearance( BOARD_ITEM* aItem, wxString* aSource ) c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, int* aClearance,
|
bool BOARD_CONNECTED_ITEM::GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer,
|
||||||
wxString* aSource ) const
|
int* aClearance, wxString* aSource ) const
|
||||||
{
|
{
|
||||||
DRC_RULE* rule = GetRule( this, aItem, CLEARANCE_CONSTRAINT );
|
const DRC_CONSTRAINT* constraint = GetConstraint( this, aItem, DRC_RULE_ID_CLEARANCE, aLayer,
|
||||||
|
aSource );
|
||||||
|
|
||||||
if( rule )
|
if( constraint )
|
||||||
{
|
{
|
||||||
if( aSource )
|
if( aSource )
|
||||||
*aSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
*aSource = wxString::Format( _( "'%s' rule" ), *aSource );
|
||||||
|
|
||||||
*aClearance = rule->m_Clearance.Min;
|
*aClearance = constraint->m_Value.Min();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,20 +161,24 @@ public:
|
||||||
* returned clearance is the greater of this object's NETCLASS clearance and
|
* returned clearance is the greater of this object's NETCLASS clearance and
|
||||||
* aItem's NETCLASS clearance. If \a aItem is NULL, then this objects clearance
|
* aItem's NETCLASS clearance. If \a aItem is NULL, then this objects clearance
|
||||||
* is returned.
|
* is returned.
|
||||||
|
* @param aLayer the layer in question
|
||||||
* @param aItem is an optional BOARD_ITEM
|
* @param aItem is an optional BOARD_ITEM
|
||||||
* @param aSource [out] optionally reports the source as a user-readable string
|
* @param aSource [out] optionally reports the source as a user-readable string
|
||||||
* @return int - the clearance in internal units.
|
* @return int - the clearance in internal units.
|
||||||
*/
|
*/
|
||||||
virtual int GetClearance( BOARD_ITEM* aItem = nullptr, wxString* aSource = nullptr ) const;
|
virtual int GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem = nullptr,
|
||||||
|
wxString* aSource = nullptr ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetRuleClearance
|
* Function GetRuleClearance
|
||||||
* returns any rule-based clearance.
|
* returns any rule-based clearance.
|
||||||
|
* @param aLayer the current layer under test
|
||||||
* @param aClearance [out] the clearance value in internal units
|
* @param aClearance [out] the clearance value in internal units
|
||||||
* @param aSource [out] reports the source as a user-readable string
|
* @param aSource [out] reports the source as a user-readable string
|
||||||
* @return true if a rule was fired
|
* @return true if a rule was fired
|
||||||
*/
|
*/
|
||||||
virtual bool GetRuleClearance( BOARD_ITEM* aItem, int* aClearance, wxString* aSource ) const;
|
virtual bool GetRuleClearance( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int* aClearance,
|
||||||
|
wxString* aSource ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetLocalClearanceOverrides
|
* Function GetLocalClearanceOverrides
|
||||||
|
|
|
@ -822,7 +822,13 @@ int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue()
|
||||||
clearance = std::max( clearance, netclass.second->GetClearance() );
|
clearance = std::max( clearance, netclass.second->GetClearance() );
|
||||||
|
|
||||||
for( const DRC_RULE* rule : m_DRCRules )
|
for( const DRC_RULE* rule : m_DRCRules )
|
||||||
clearance = std::max( clearance, rule->m_Clearance.Min );
|
{
|
||||||
|
for( const DRC_CONSTRAINT& constraint : rule->m_Constraints )
|
||||||
|
{
|
||||||
|
if( constraint.m_Type == DRC_RULE_ID_CLEARANCE )
|
||||||
|
clearance = std::max( clearance, constraint.m_Value.Min() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return clearance;
|
return clearance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -825,7 +825,7 @@ void D_PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString source;
|
wxString source;
|
||||||
int clearance = GetClearance( nullptr, &source );
|
int clearance = GetClearance( GetLayer(), nullptr, &source );
|
||||||
|
|
||||||
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
||||||
msg2.Printf( _( "(from %s)" ), source );
|
msg2.Printf( _( "(from %s)" ), source );
|
||||||
|
|
|
@ -133,15 +133,16 @@ void TRACK::GetWidthConstraints( int* aMin, int* aMax, wxString* aSource ) const
|
||||||
// Not currently implemented
|
// Not currently implemented
|
||||||
|
|
||||||
// LEVEL 2: Rules
|
// LEVEL 2: Rules
|
||||||
DRC_RULE* rule = GetRule( this, nullptr, TRACK_CONSTRAINT );
|
const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_TRACK, m_Layer,
|
||||||
|
aSource );
|
||||||
|
|
||||||
if( rule )
|
if( constraint )
|
||||||
{
|
{
|
||||||
*aMin = rule->m_TrackConstraint.Min;
|
*aMin = constraint->m_Value.Min();
|
||||||
*aMax = rule->m_TrackConstraint.Max;
|
*aMax = constraint->m_Value.Max();
|
||||||
|
|
||||||
if( aSource )
|
if( aSource )
|
||||||
*aSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
*aSource = wxString::Format( _( "'%s' rule" ), *aSource );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -160,16 +161,17 @@ void TRACK::GetWidthConstraints( int* aMin, int* aMax, wxString* aSource ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int VIA::GetMinAnnulus( wxString* aSource ) const
|
int VIA::GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const
|
||||||
{
|
{
|
||||||
DRC_RULE* rule = GetRule( this, nullptr, ANNULUS_CONSTRAINT );
|
const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_ANNULUS, aLayer,
|
||||||
|
aSource );
|
||||||
|
|
||||||
if( rule )
|
if( constraint )
|
||||||
{
|
{
|
||||||
if( aSource )
|
if( aSource )
|
||||||
*aSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
*aSource = wxString::Format( _( "'%s' rule" ), *aSource );
|
||||||
|
|
||||||
return rule->m_MinAnnulusWidth;
|
return constraint->m_Value.Min();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -493,7 +495,7 @@ unsigned int TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
|
||||||
const BOX2I TRACK::ViewBBox() const
|
const BOX2I TRACK::ViewBBox() const
|
||||||
{
|
{
|
||||||
BOX2I bbox = GetBoundingBox();
|
BOX2I bbox = GetBoundingBox();
|
||||||
bbox.Inflate( 2 * GetClearance() );
|
bbox.Inflate( 2 * GetClearance( GetLayer() ) );
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,7 +614,7 @@ void TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int clearance = GetClearance( nullptr, &source );
|
int clearance = GetClearance( GetLayer(), nullptr, &source );
|
||||||
|
|
||||||
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
||||||
msg2.Printf( _( "(from %s)" ), source );
|
msg2.Printf( _( "(from %s)" ), source );
|
||||||
|
@ -685,13 +687,13 @@ void VIA::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>&
|
||||||
|
|
||||||
aList.emplace_back( _( "Drill" ), msg, RED );
|
aList.emplace_back( _( "Drill" ), msg, RED );
|
||||||
|
|
||||||
int clearance = GetClearance( nullptr, &source );
|
int clearance = GetClearance( GetLayer(), nullptr, &source );
|
||||||
|
|
||||||
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
||||||
msg2.Printf( _( "(from %s)" ), source );
|
msg2.Printf( _( "(from %s)" ), source );
|
||||||
aList.emplace_back( msg, msg2, BLACK );
|
aList.emplace_back( msg, msg2, BLACK );
|
||||||
|
|
||||||
int minAnnulus = GetMinAnnulus( &source );
|
int minAnnulus = GetMinAnnulus( GetLayer(), &source );
|
||||||
|
|
||||||
msg.Printf( _( "Min Annulus: %s" ), MessageTextFromValue( units, minAnnulus, true ) );
|
msg.Printf( _( "Min Annulus: %s" ), MessageTextFromValue( units, minAnnulus, true ) );
|
||||||
msg2.Printf( _( "(from %s)" ), source );
|
msg2.Printf( _( "(from %s)" ), source );
|
||||||
|
|
|
@ -442,7 +442,7 @@ public:
|
||||||
void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int GetMinAnnulus( wxString* aSource ) const;
|
int GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function SetDrill
|
* Function SetDrill
|
||||||
|
|
|
@ -336,7 +336,7 @@ int ZONE_CONTAINER::GetThermalReliefCopperBridge( D_PAD* aPad ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ZONE_CONTAINER::GetKeepouts( std::map<int, wxString>* aSources ) const
|
int ZONE_CONTAINER::GetKeepouts( PCB_LAYER_ID aLayer, std::map<int, wxString>* aSources ) const
|
||||||
{
|
{
|
||||||
wxString source;
|
wxString source;
|
||||||
int keepouts = 0;
|
int keepouts = 0;
|
||||||
|
@ -370,41 +370,42 @@ int ZONE_CONTAINER::GetKeepouts( std::map<int, wxString>* aSources ) const
|
||||||
setFlag( DISALLOW_ZONES );
|
setFlag( DISALLOW_ZONES );
|
||||||
}
|
}
|
||||||
|
|
||||||
DRC_RULE* rule = GetRule( this, nullptr, DISALLOW_CONSTRAINT );
|
const DRC_CONSTRAINT* constraint = GetConstraint( this, nullptr, DRC_RULE_ID_DISALLOW, aLayer,
|
||||||
|
&source );
|
||||||
|
|
||||||
if( rule )
|
if( constraint )
|
||||||
{
|
{
|
||||||
if( aSources )
|
if( aSources )
|
||||||
source = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
source = wxString::Format( _( "'%s' rule" ), source );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_VIAS ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_VIAS ) > 0 )
|
||||||
setFlag( DISALLOW_VIAS );
|
setFlag( DISALLOW_VIAS );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_MICRO_VIAS ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_MICRO_VIAS ) > 0 )
|
||||||
setFlag( DISALLOW_MICRO_VIAS );
|
setFlag( DISALLOW_MICRO_VIAS );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_BB_VIAS ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_BB_VIAS ) > 0 )
|
||||||
setFlag( DISALLOW_BB_VIAS );
|
setFlag( DISALLOW_BB_VIAS );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_TRACKS ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_TRACKS ) > 0 )
|
||||||
setFlag( DISALLOW_TRACKS );
|
setFlag( DISALLOW_TRACKS );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_PADS ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_PADS ) > 0 )
|
||||||
setFlag( DISALLOW_PADS );
|
setFlag( DISALLOW_PADS );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_ZONES ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_ZONES ) > 0 )
|
||||||
setFlag( DISALLOW_ZONES );
|
setFlag( DISALLOW_ZONES );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_TEXTS ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_TEXTS ) > 0 )
|
||||||
setFlag( DISALLOW_TEXTS );
|
setFlag( DISALLOW_TEXTS );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_GRAPHICS ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_GRAPHICS ) > 0 )
|
||||||
setFlag( DISALLOW_GRAPHICS );
|
setFlag( DISALLOW_GRAPHICS );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_HOLES ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_HOLES ) > 0 )
|
||||||
setFlag( DISALLOW_HOLES );
|
setFlag( DISALLOW_HOLES );
|
||||||
|
|
||||||
if( ( rule->m_DisallowFlags & DISALLOW_FOOTPRINTS ) > 0 )
|
if( ( constraint->m_DisallowFlags & DISALLOW_FOOTPRINTS ) > 0 )
|
||||||
setFlag( DISALLOW_FOOTPRINTS );
|
setFlag( DISALLOW_FOOTPRINTS );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,7 +679,7 @@ void ZONE_CONTAINER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
|
||||||
aList.emplace_back( _( "Filled Area" ), msg, BLUE );
|
aList.emplace_back( _( "Filled Area" ), msg, BLUE );
|
||||||
|
|
||||||
wxString source;
|
wxString source;
|
||||||
int clearance = GetClearance( nullptr, &source );
|
int clearance = GetClearance( GetLayer(), nullptr, &source );
|
||||||
|
|
||||||
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
msg.Printf( _( "Min Clearance: %s" ), MessageTextFromValue( units, clearance, true ) );
|
||||||
msg2.Printf( _( "(from %s)" ), source );
|
msg2.Printf( _( "(from %s)" ), source );
|
||||||
|
@ -1374,6 +1375,8 @@ static struct ZONE_CONTAINER_DESC
|
||||||
//&ZONE_CONTAINER::SetIsFilled, &ZONE_CONTAINER::IsFilled ) );
|
//&ZONE_CONTAINER::SetIsFilled, &ZONE_CONTAINER::IsFilled ) );
|
||||||
propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _( "Min Thickness" ),
|
propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, int>( _( "Min Thickness" ),
|
||||||
&ZONE_CONTAINER::SetMinThickness, &ZONE_CONTAINER::GetMinThickness, PROPERTY_DISPLAY::DISTANCE ) );
|
&ZONE_CONTAINER::SetMinThickness, &ZONE_CONTAINER::GetMinThickness, PROPERTY_DISPLAY::DISTANCE ) );
|
||||||
|
propMgr.AddProperty( new PROPERTY<ZONE_CONTAINER, wxString>( _( "Name" ),
|
||||||
|
&ZONE_CONTAINER::SetZoneName, &ZONE_CONTAINER::GetZoneName ) );
|
||||||
// TODO pad connection, thermal relief gap, thermal relief copper bridge
|
// TODO pad connection, thermal relief gap, thermal relief copper bridge
|
||||||
}
|
}
|
||||||
} _ZONE_CONTAINER_DESC;
|
} _ZONE_CONTAINER_DESC;
|
||||||
|
|
|
@ -723,7 +723,7 @@ public:
|
||||||
* flag.
|
* flag.
|
||||||
* @return a bitset of DISALLOW_* flags.
|
* @return a bitset of DISALLOW_* flags.
|
||||||
*/
|
*/
|
||||||
int GetKeepouts( std::map<int, wxString>* aSources = nullptr ) const;
|
int GetKeepouts( PCB_LAYER_ID aLayer, std::map<int, wxString>* aSources = nullptr ) const;
|
||||||
|
|
||||||
void SetIsKeepout( bool aEnable ) { m_isKeepout = aEnable; }
|
void SetIsKeepout( bool aEnable ) { m_isKeepout = aEnable; }
|
||||||
void SetDoNotAllowCopperPour( bool aEnable ) { m_doNotAllowCopperPour = aEnable; }
|
void SetDoNotAllowCopperPour( bool aEnable ) { m_doNotAllowCopperPour = aEnable; }
|
||||||
|
|
|
@ -179,20 +179,37 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
|
||||||
if( sexprs.empty() )
|
if( sexprs.empty() )
|
||||||
tokens = "rule version";
|
tokens = "rule version";
|
||||||
else if( sexprs.top() == "rule" )
|
else if( sexprs.top() == "rule" )
|
||||||
tokens = "condition constraint disallow layer";
|
tokens = "condition constraint layer";
|
||||||
else if( sexprs.top() == "constraint" )
|
else if( sexprs.top() == "constraint" )
|
||||||
tokens = "max min opt";
|
tokens = "max min opt";
|
||||||
}
|
}
|
||||||
else if( context == SEXPR_TOKEN )
|
else if( context == SEXPR_TOKEN )
|
||||||
{
|
{
|
||||||
if( sexprs.empty() )
|
if( sexprs.empty() )
|
||||||
/* badly formed grammar */;
|
{
|
||||||
|
/* badly formed grammar */
|
||||||
|
}
|
||||||
else if( sexprs.top() == "constraint" )
|
else if( sexprs.top() == "constraint" )
|
||||||
tokens = "annulus_width clearance hole track_width";
|
{
|
||||||
else if( sexprs.top() == "disallow" )
|
tokens = "annulus_width clearance disallow hole track_width";
|
||||||
|
}
|
||||||
|
else if( sexprs.top() == "disallow"
|
||||||
|
|| sexprs.top() == "buried_via"
|
||||||
|
|| sexprs.top() == "graphic"
|
||||||
|
|| sexprs.top() == "hole"
|
||||||
|
|| sexprs.top() == "micro_via"
|
||||||
|
|| sexprs.top() == "pad"
|
||||||
|
|| sexprs.top() == "text"
|
||||||
|
|| sexprs.top() == "track"
|
||||||
|
|| sexprs.top() == "via"
|
||||||
|
|| sexprs.top() == "zone" )
|
||||||
|
{
|
||||||
tokens = "buried_via graphic hole micro_via pad text track via zone";
|
tokens = "buried_via graphic hole micro_via pad text track via zone";
|
||||||
|
}
|
||||||
else if( sexprs.top() == "layer" )
|
else if( sexprs.top() == "layer" )
|
||||||
|
{
|
||||||
tokens = "inner outer \"x\"";
|
tokens = "inner outer \"x\"";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( context == STRING && expr_context == STRUCT_REF )
|
else if( context == STRING && expr_context == STRUCT_REF )
|
||||||
{
|
{
|
||||||
|
@ -327,11 +344,16 @@ void PANEL_SETUP_RULES::OnSyntaxHelp( wxHyperlinkEvent& aEvent )
|
||||||
msg << _( "Rule Clauses" );
|
msg << _( "Rule Clauses" );
|
||||||
msg << "</b>"
|
msg << "</b>"
|
||||||
"<pre>"
|
"<pre>"
|
||||||
"(disallow <item_type>)\r"
|
|
||||||
"(constraint <constraint_type> ...)\r"
|
"(constraint <constraint_type> ...)\r"
|
||||||
"(condition \"<expression>\")\r"
|
"(condition \"<expression>\")\r"
|
||||||
"\r</pre>"
|
"\r</pre>"
|
||||||
"<b>";
|
"<b>";
|
||||||
|
msg << _( "Constraint Types" );
|
||||||
|
msg << "</b>"
|
||||||
|
"<pre>"
|
||||||
|
"clearance annulus_width track_width hole dissallow\r"
|
||||||
|
"\r</pre>"
|
||||||
|
"<b>";
|
||||||
msg << _( "Item Types" );
|
msg << _( "Item Types" );
|
||||||
msg << "</b>"
|
msg << "</b>"
|
||||||
"<pre>"
|
"<pre>"
|
||||||
|
@ -340,17 +362,11 @@ void PANEL_SETUP_RULES::OnSyntaxHelp( wxHyperlinkEvent& aEvent )
|
||||||
"hole buried_via graphic\r"
|
"hole buried_via graphic\r"
|
||||||
"\r</pre>"
|
"\r</pre>"
|
||||||
"<b>";
|
"<b>";
|
||||||
msg << _( "Constraint Types" );
|
|
||||||
msg << "</b>"
|
|
||||||
"<pre>"
|
|
||||||
"clearance annulus_width track_width hole\r"
|
|
||||||
"\r</pre>"
|
|
||||||
"<b>";
|
|
||||||
msg << _( "Examples" );
|
msg << _( "Examples" );
|
||||||
msg << "</b>"
|
msg << "</b>"
|
||||||
"<pre>"
|
"<pre>"
|
||||||
"(rule \"copper keepout\"\r"
|
"(rule \"copper keepout\"\r"
|
||||||
" (disallow track) (disallow via) (disallow zone)\r"
|
" (constraint disallow track via zone)\r"
|
||||||
" (condition \"A.name == 'no_copper'\"))\r"
|
" (condition \"A.name == 'no_copper'\"))\r"
|
||||||
"\r"
|
"\r"
|
||||||
"(rule \"BGA neckdown\"\r"
|
"(rule \"BGA neckdown\"\r"
|
||||||
|
|
|
@ -502,10 +502,7 @@ void DRC::testPadClearances( BOARD_COMMIT& aCommit )
|
||||||
static DRAWSEGMENT dummyEdge;
|
static DRAWSEGMENT dummyEdge;
|
||||||
dummyEdge.SetLayer( Edge_Cuts );
|
dummyEdge.SetLayer( Edge_Cuts );
|
||||||
|
|
||||||
if( pad->GetRuleClearance( &dummyEdge, &minClearance, &m_clearanceSource ) )
|
pad->GetRuleClearance( &dummyEdge, pad->GetLayer(), &minClearance, &m_clearanceSource );
|
||||||
{
|
|
||||||
/* minClearance and m_clearanceSource set in GetRuleClearance() */;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
||||||
{
|
{
|
||||||
|
@ -723,7 +720,8 @@ void DRC::testZones( BOARD_COMMIT& aCommit )
|
||||||
// Get clearance used in zone to zone test. The policy used to
|
// Get clearance used in zone to zone test. The policy used to
|
||||||
// obtain that value is now part of the zone object itself by way of
|
// obtain that value is now part of the zone object itself by way of
|
||||||
// ZONE_CONTAINER::GetClearance().
|
// ZONE_CONTAINER::GetClearance().
|
||||||
int zone2zoneClearance = zoneRef->GetClearance( zoneToTest, &m_clearanceSource );
|
int zone2zoneClearance = zoneRef->GetClearance( zoneRef->GetLayer(), zoneToTest,
|
||||||
|
&m_clearanceSource );
|
||||||
|
|
||||||
// Keepout areas have no clearance, so set zone2zoneClearance to 1
|
// Keepout areas have no clearance, so set zone2zoneClearance to 1
|
||||||
// ( zone2zoneClearance = 0 can create problems in test functions)
|
// ( zone2zoneClearance = 0 can create problems in test functions)
|
||||||
|
@ -907,12 +905,12 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
||||||
SHAPE_RECT bboxShape( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
|
SHAPE_RECT bboxShape( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
|
||||||
|
|
||||||
// Test tracks and vias
|
// Test tracks and vias
|
||||||
for( auto track : m_pcb->Tracks() )
|
for( TRACK* track : m_pcb->Tracks() )
|
||||||
{
|
{
|
||||||
if( !track->IsOnLayer( aItem->GetLayer() ) )
|
if( !track->IsOnLayer( aItem->GetLayer() ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int minClearance = track->GetClearance( aItem, &m_clearanceSource );
|
int minClearance = track->GetClearance( track->GetLayer(), aItem, &m_clearanceSource );
|
||||||
int actual = INT_MAX;
|
int actual = INT_MAX;
|
||||||
wxPoint pos;
|
wxPoint pos;
|
||||||
|
|
||||||
|
@ -954,7 +952,7 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test pads
|
// Test pads
|
||||||
for( auto pad : m_pcb->GetPads() )
|
for( D_PAD* pad : m_pcb->GetPads() )
|
||||||
{
|
{
|
||||||
if( !pad->IsOnLayer( aItem->GetLayer() ) )
|
if( !pad->IsOnLayer( aItem->GetLayer() ) )
|
||||||
continue;
|
continue;
|
||||||
|
@ -963,7 +961,7 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
|
||||||
if( drawItem && pad->GetParent() == drawItem->GetParent() )
|
if( drawItem && pad->GetParent() == drawItem->GetParent() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int minClearance = pad->GetClearance( aItem, &m_clearanceSource );
|
int minClearance = pad->GetClearance( aItem->GetLayer(), aItem, &m_clearanceSource );
|
||||||
int actual = INT_MAX;
|
int actual = INT_MAX;
|
||||||
|
|
||||||
// Fast test to detect a pad candidate inside the text bounding box
|
// Fast test to detect a pad candidate inside the text bounding box
|
||||||
|
@ -1136,7 +1134,8 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
||||||
|
|
||||||
if( pad->GetDrillSize().x )
|
if( pad->GetDrillSize().x )
|
||||||
{
|
{
|
||||||
int minClearance = aRefPad->GetClearance( nullptr, &m_clearanceSource );
|
int minClearance = aRefPad->GetClearance( aRefPad->GetLayer(), nullptr,
|
||||||
|
&m_clearanceSource );
|
||||||
int actual;
|
int actual;
|
||||||
|
|
||||||
if( aRefPad->Collide( pad->GetEffectiveHoleShape(), minClearance, &actual ) )
|
if( aRefPad->Collide( pad->GetEffectiveHoleShape(), minClearance, &actual ) )
|
||||||
|
@ -1159,7 +1158,8 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
||||||
|
|
||||||
if( aRefPad->GetDrillSize().x )
|
if( aRefPad->GetDrillSize().x )
|
||||||
{
|
{
|
||||||
int minClearance = pad->GetClearance( nullptr, &m_clearanceSource );
|
int minClearance = pad->GetClearance( pad->GetLayer(), nullptr,
|
||||||
|
&m_clearanceSource );
|
||||||
int actual;
|
int actual;
|
||||||
|
|
||||||
if( pad->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) )
|
if( pad->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) )
|
||||||
|
@ -1216,25 +1216,28 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int minClearance = aRefPad->GetClearance( pad, &m_clearanceSource );
|
for( PCB_LAYER_ID layer : aRefPad->GetLayerSet().Seq() )
|
||||||
int clearanceAllowed = minClearance - m_pcb->GetDesignSettings().GetDRCEpsilon();
|
|
||||||
int actual;
|
|
||||||
|
|
||||||
if( aRefPad->Collide( pad, clearanceAllowed, &actual ) )
|
|
||||||
{
|
{
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
int minClearance = aRefPad->GetClearance( layer, pad, &m_clearanceSource );
|
||||||
|
int clearanceAllowed = minClearance - m_pcb->GetDesignSettings().GetDRCEpsilon();
|
||||||
|
int actual;
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
if( aRefPad->Collide( pad, clearanceAllowed, &actual ) )
|
||||||
m_clearanceSource,
|
{
|
||||||
MessageTextFromValue( userUnits(), minClearance, true ),
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
|
||||||
MessageTextFromValue( userUnits(), actual, true ) );
|
|
||||||
|
|
||||||
drcItem->SetErrorMessage( m_msg );
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||||
drcItem->SetItems( aRefPad, pad );
|
m_clearanceSource,
|
||||||
|
MessageTextFromValue( userUnits(), minClearance, true ),
|
||||||
|
MessageTextFromValue( userUnits(), actual, true ) );
|
||||||
|
|
||||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() );
|
drcItem->SetErrorMessage( m_msg );
|
||||||
addMarkerToPcb( aCommit, marker );
|
drcItem->SetItems( aRefPad, pad );
|
||||||
return false;
|
|
||||||
|
MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() );
|
||||||
|
addMarkerToPcb( aCommit, marker );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
{
|
{
|
||||||
VIA *refvia = static_cast<VIA*>( aRefSeg );
|
VIA *refvia = static_cast<VIA*>( aRefSeg );
|
||||||
int viaAnnulus = ( refvia->GetWidth() - refvia->GetDrill() ) / 2;
|
int viaAnnulus = ( refvia->GetWidth() - refvia->GetDrill() ) / 2;
|
||||||
int minAnnulus = refvia->GetMinAnnulus( &m_clearanceSource );
|
int minAnnulus = refvia->GetMinAnnulus( refvia->GetLayer(), &m_clearanceSource );
|
||||||
|
|
||||||
// test if the via size is smaller than minimum
|
// test if the via size is smaller than minimum
|
||||||
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
if( refvia->GetViaType() == VIATYPE::MICROVIA )
|
||||||
|
@ -280,20 +280,22 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
|
|
||||||
if( pad->GetDrillSize().x > 0 )
|
if( pad->GetDrillSize().x > 0 )
|
||||||
{
|
{
|
||||||
const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape();
|
const SHAPE_SEGMENT* slot = pad->GetEffectiveHoleShape();
|
||||||
DRC_RULE* rule = GetRule( aRefSeg, pad, CLEARANCE_CONSTRAINT );
|
const DRC_CONSTRAINT* constraint = GetConstraint( aRefSeg, pad,
|
||||||
|
DRC_RULE_ID_CLEARANCE, refLayer,
|
||||||
|
&m_clearanceSource );
|
||||||
int minClearance;
|
int minClearance;
|
||||||
int actual;
|
int actual;
|
||||||
|
|
||||||
if( rule )
|
if( constraint )
|
||||||
{
|
{
|
||||||
m_clearanceSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
m_clearanceSource = wxString::Format( _( "'%s' rule" ), m_clearanceSource );
|
||||||
minClearance = rule->m_Clearance.Min;
|
minClearance = constraint->m_Value.Min();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
minClearance = aRefSeg->GetClearance( nullptr, &m_clearanceSource );
|
minClearance = aRefSeg->GetClearance( refLayer, nullptr,
|
||||||
|
&m_clearanceSource );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( slot->Collide( &refSeg, minClearance + bds.GetDRCEpsilon(), &actual ) )
|
if( slot->Collide( &refSeg, minClearance + bds.GetDRCEpsilon(), &actual ) )
|
||||||
|
@ -316,7 +318,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int minClearance = aRefSeg->GetClearance( pad, &m_clearanceSource );
|
int minClearance = aRefSeg->GetClearance( aRefSeg->GetLayer(), pad,
|
||||||
|
&m_clearanceSource );
|
||||||
int actual;
|
int actual;
|
||||||
|
|
||||||
if( pad->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual ) )
|
if( pad->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual ) )
|
||||||
|
@ -383,7 +386,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
if( !trackBB.Intersects( refSegBB ) )
|
if( !trackBB.Intersects( refSegBB ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int minClearance = aRefSeg->GetClearance( track, &m_clearanceSource );
|
int minClearance = aRefSeg->GetClearance( aRefSeg->GetLayer(), track,
|
||||||
|
&m_clearanceSource );
|
||||||
int actual;
|
int actual;
|
||||||
SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
|
SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
|
||||||
|
|
||||||
|
@ -447,7 +451,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
// (1 micron)
|
// (1 micron)
|
||||||
#define THRESHOLD_DIST Millimeter2iu( 0.001 )
|
#define THRESHOLD_DIST Millimeter2iu( 0.001 )
|
||||||
|
|
||||||
int minClearance = aRefSeg->GetClearance( zone, &m_clearanceSource );
|
int minClearance = aRefSeg->GetClearance( aRefSeg->GetLayer(), zone,
|
||||||
|
&m_clearanceSource );
|
||||||
int widths = refSegWidth / 2;
|
int widths = refSegWidth / 2;
|
||||||
int allowedDist = minClearance + widths + THRESHOLD_DIST;
|
int allowedDist = minClearance + widths + THRESHOLD_DIST;
|
||||||
int actual;
|
int actual;
|
||||||
|
@ -483,10 +488,8 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
static DRAWSEGMENT dummyEdge;
|
static DRAWSEGMENT dummyEdge;
|
||||||
dummyEdge.SetLayer( Edge_Cuts );
|
dummyEdge.SetLayer( Edge_Cuts );
|
||||||
|
|
||||||
if( aRefSeg->GetRuleClearance( &dummyEdge, &minClearance, &m_clearanceSource ) )
|
aRefSeg->GetRuleClearance( &dummyEdge, aRefSeg->GetLayer(), &minClearance,
|
||||||
{
|
&m_clearanceSource );
|
||||||
/* minClearance and m_clearanceSource set in GetRuleClearance() */;
|
|
||||||
}
|
|
||||||
|
|
||||||
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
SEG testSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
|
||||||
int halfWidth = refSegWidth / 2;
|
int halfWidth = refSegWidth / 2;
|
||||||
|
|
|
@ -84,21 +84,28 @@ bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad )
|
||||||
bool success = true;
|
bool success = true;
|
||||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||||
|
|
||||||
int holeSize = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
|
// drilled holes go all the way through, so which layer we use shouldn't matter
|
||||||
|
PCB_LAYER_ID layer = F_Cu;
|
||||||
|
int holeSize = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
|
||||||
|
|
||||||
if( holeSize == 0 )
|
if( holeSize == 0 )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( !bds.Ignore( DRCE_TOO_SMALL_DRILL ) )
|
if( !bds.Ignore( DRCE_TOO_SMALL_DRILL ) )
|
||||||
{
|
{
|
||||||
int minHole = bds.m_MinThroughDrill;
|
int minHole;
|
||||||
wxString minHoleSource = _( "board minimum" );
|
const DRC_CONSTRAINT* constraint = GetConstraint( aPad, nullptr, DRC_RULE_ID_HOLE_SIZE,
|
||||||
DRC_RULE* rule = GetRule( aPad, nullptr, HOLE_CONSTRAINT );
|
layer, &m_source );
|
||||||
|
|
||||||
if( rule )
|
if( constraint )
|
||||||
{
|
{
|
||||||
minHole = rule->m_MinHole;
|
minHole = constraint->m_Value.Min();
|
||||||
minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
m_source = wxString::Format( _( "'%s' rule" ), m_source );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minHole = bds.m_MinThroughDrill;
|
||||||
|
m_source = _( "board minimum" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( holeSize < minHole )
|
if( holeSize < minHole )
|
||||||
|
@ -106,7 +113,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad )
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
||||||
minHoleSource,
|
m_source,
|
||||||
MessageTextFromValue( m_units, minHole, true ),
|
MessageTextFromValue( m_units, minHole, true ),
|
||||||
MessageTextFromValue( m_units, holeSize, true ) );
|
MessageTextFromValue( m_units, holeSize, true ) );
|
||||||
|
|
||||||
|
@ -132,16 +139,24 @@ bool DRC_DRILLED_HOLE_TESTER::checkVia( VIA* via )
|
||||||
bool success = true;
|
bool success = true;
|
||||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||||
|
|
||||||
|
// drilled holes go all the way through, so which layer we use shouldn't matter
|
||||||
|
PCB_LAYER_ID layer = F_Cu;
|
||||||
|
|
||||||
if( !bds.Ignore( DRCE_TOO_SMALL_DRILL ) )
|
if( !bds.Ignore( DRCE_TOO_SMALL_DRILL ) )
|
||||||
{
|
{
|
||||||
int minHole = bds.m_MinThroughDrill;
|
int minHole;
|
||||||
wxString minHoleSource = _( "board minimum" );
|
const DRC_CONSTRAINT* constraint = GetConstraint( via, nullptr, DRC_RULE_ID_HOLE_SIZE,
|
||||||
DRC_RULE* rule = GetRule( via, nullptr, HOLE_CONSTRAINT );
|
layer, &m_source );
|
||||||
|
|
||||||
if( rule )
|
if( constraint )
|
||||||
{
|
{
|
||||||
minHole = rule->m_MinHole;
|
minHole = constraint->m_Value.Min();
|
||||||
minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
m_source = wxString::Format( _( "'%s' rule" ), m_source );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minHole = bds.m_MinThroughDrill;
|
||||||
|
m_source = _( "board minimum" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( via->GetDrillValue() < minHole )
|
if( via->GetDrillValue() < minHole )
|
||||||
|
@ -149,7 +164,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkVia( VIA* via )
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
||||||
minHoleSource,
|
m_source,
|
||||||
MessageTextFromValue( m_units, minHole, true ),
|
MessageTextFromValue( m_units, minHole, true ),
|
||||||
MessageTextFromValue( m_units, via->GetDrillValue(), true ) );
|
MessageTextFromValue( m_units, via->GetDrillValue(), true ) );
|
||||||
|
|
||||||
|
@ -175,16 +190,25 @@ bool DRC_DRILLED_HOLE_TESTER::checkMicroVia( VIA* via )
|
||||||
bool success = true;
|
bool success = true;
|
||||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||||
|
|
||||||
|
// while microvia holes don't necessarily go all the way through, they can't be different
|
||||||
|
// sizes on different layers so we should still be safe enough using a fixed layer.
|
||||||
|
PCB_LAYER_ID layer = F_Cu;
|
||||||
|
|
||||||
if( !bds.Ignore( DRCE_TOO_SMALL_MICROVIA_DRILL ) )
|
if( !bds.Ignore( DRCE_TOO_SMALL_MICROVIA_DRILL ) )
|
||||||
{
|
{
|
||||||
int minHole = bds.m_MicroViasMinDrill;
|
int minHole;
|
||||||
wxString minHoleSource = _( "board minimum" );
|
const DRC_CONSTRAINT* constraint = GetConstraint( via, nullptr, DRC_RULE_ID_HOLE_SIZE,
|
||||||
DRC_RULE* rule = GetRule( via, nullptr, HOLE_CONSTRAINT );
|
layer, &m_source );
|
||||||
|
|
||||||
if( rule )
|
if( constraint )
|
||||||
{
|
{
|
||||||
minHole = rule->m_MinHole;
|
minHole = constraint->m_Value.Min();
|
||||||
minHoleSource = wxString::Format( _( "'%s' rule" ), rule->m_Name );
|
m_source = wxString::Format( _( "'%s' rule" ), m_source );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minHole = bds.m_MicroViasMinDrill;
|
||||||
|
m_source = _( "board minimum" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( via->GetDrillValue() < minHole )
|
if( via->GetDrillValue() < minHole )
|
||||||
|
@ -192,7 +216,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkMicroVia( VIA* via )
|
||||||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_MICROVIA_DRILL );
|
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_MICROVIA_DRILL );
|
||||||
|
|
||||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
|
||||||
minHoleSource,
|
m_source,
|
||||||
MessageTextFromValue( m_units, minHole, true ),
|
MessageTextFromValue( m_units, minHole, true ),
|
||||||
MessageTextFromValue( m_units, via->GetDrillValue(), true ) );
|
MessageTextFromValue( m_units, via->GetDrillValue(), true ) );
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,8 @@ private:
|
||||||
std::vector<DRILLED_HOLE> m_holes;
|
std::vector<DRILLED_HOLE> m_holes;
|
||||||
int m_largestRadius;
|
int m_largestRadius;
|
||||||
|
|
||||||
wxString m_msg; // Construct only once for performance
|
wxString m_source; // Construct only once for performance
|
||||||
|
wxString m_msg; // Construct only once for performance
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DRC_DRILLED_HOLE_TESTER__H
|
#endif // DRC_DRILLED_HOLE_TESTER__H
|
||||||
|
|
|
@ -51,7 +51,8 @@ bool DRC_KEEPOUT_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard )
|
||||||
// Test keepout areas for vias, tracks and pads inside keepout areas
|
// Test keepout areas for vias, tracks and pads inside keepout areas
|
||||||
for( ZONE_CONTAINER* area : areasToInspect )
|
for( ZONE_CONTAINER* area : areasToInspect )
|
||||||
{
|
{
|
||||||
m_keepoutFlags = area->GetKeepouts( &m_sources );
|
// JEY TODO: our existing keepout strategy needs a work-over for rules....
|
||||||
|
m_keepoutFlags = area->GetKeepouts( F_Cu, &m_sources );
|
||||||
|
|
||||||
if( m_keepoutFlags > 0 )
|
if( m_keepoutFlags > 0 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,13 +23,15 @@
|
||||||
|
|
||||||
|
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <drc/drc_rule.h>
|
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
#include <class_board_item.h>
|
#include <class_board_item.h>
|
||||||
|
|
||||||
|
#include <drc/drc_rule.h>
|
||||||
#include <pcb_expr_evaluator.h>
|
#include <pcb_expr_evaluator.h>
|
||||||
|
|
||||||
|
|
||||||
DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint )
|
const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
|
||||||
|
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName )
|
||||||
{
|
{
|
||||||
BOARD* board = aItem->GetBoard();
|
BOARD* board = aItem->GetBoard();
|
||||||
|
|
||||||
|
@ -38,13 +40,32 @@ DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstr
|
||||||
|
|
||||||
for( DRC_RULE* rule : board->GetDesignSettings().m_DRCRules )
|
for( DRC_RULE* rule : board->GetDesignSettings().m_DRCRules )
|
||||||
{
|
{
|
||||||
if( ( rule->m_ConstraintFlags & aConstraint ) > 0 )
|
if( !rule->m_LayerCondition.test( aLayer ) )
|
||||||
{
|
continue;
|
||||||
if( rule->m_Condition.EvaluateFor( aItem, bItem ) )
|
|
||||||
return rule;
|
|
||||||
|
|
||||||
if( bItem && rule->m_Condition.EvaluateFor( bItem, aItem ) )
|
for( const DRC_CONSTRAINT& constraint : rule->m_Constraints )
|
||||||
return rule;
|
{
|
||||||
|
if( constraint.m_Type != aConstraint )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !rule->m_LayerCondition.test( aLayer ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( rule->m_Condition.EvaluateFor( aItem, bItem, aLayer ) )
|
||||||
|
{
|
||||||
|
if( aRuleName )
|
||||||
|
*aRuleName = rule->m_Name;
|
||||||
|
|
||||||
|
return &constraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bItem && rule->m_Condition.EvaluateFor( bItem, aItem, aLayer ) )
|
||||||
|
{
|
||||||
|
if( aRuleName )
|
||||||
|
*aRuleName = rule->m_Name;
|
||||||
|
|
||||||
|
return &constraint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +73,17 @@ DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DRC_RULE::DRC_RULE() :
|
||||||
|
m_LayerCondition( LSET::AllLayersMask() )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DRC_RULE::~DRC_RULE()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DRC_RULE_CONDITION::DRC_RULE_CONDITION()
|
DRC_RULE_CONDITION::DRC_RULE_CONDITION()
|
||||||
{
|
{
|
||||||
m_ucode = nullptr;
|
m_ucode = nullptr;
|
||||||
|
@ -64,7 +96,8 @@ DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB )
|
bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
|
||||||
|
PCB_LAYER_ID aLayer )
|
||||||
{
|
{
|
||||||
// An unconditional rule is always true
|
// An unconditional rule is always true
|
||||||
if( m_Expression.IsEmpty() )
|
if( m_Expression.IsEmpty() )
|
||||||
|
@ -77,7 +110,7 @@ bool DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM
|
||||||
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
|
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
|
||||||
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
|
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
|
||||||
|
|
||||||
PCB_EXPR_CONTEXT ctx;
|
PCB_EXPR_CONTEXT ctx( aLayer );
|
||||||
ctx.SetItems( a, b );
|
ctx.SetItems( a, b );
|
||||||
|
|
||||||
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
|
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
|
||||||
|
@ -91,14 +124,10 @@ bool DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSou
|
||||||
if (!m_ucode)
|
if (!m_ucode)
|
||||||
m_ucode = new PCB_EXPR_UCODE;
|
m_ucode = new PCB_EXPR_UCODE;
|
||||||
|
|
||||||
PCB_EXPR_CONTEXT preflightContext;
|
PCB_EXPR_CONTEXT preflightContext( F_Cu );
|
||||||
|
|
||||||
bool ok = compiler.Compile( m_Expression.ToUTF8().data(), m_ucode, &preflightContext );
|
bool ok = compiler.Compile( m_Expression.ToUTF8().data(), m_ucode, &preflightContext );
|
||||||
|
return ok;
|
||||||
if( ok )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
#define DRC_RULE_H
|
#define DRC_RULE_H
|
||||||
|
|
||||||
#include <core/typeinfo.h>
|
#include <core/typeinfo.h>
|
||||||
#include <netclass.h>
|
|
||||||
#include <layers_id_colors_and_visibility.h>
|
#include <layers_id_colors_and_visibility.h>
|
||||||
|
#include <netclass.h>
|
||||||
#include <libeval_compiler/libeval_compiler.h>
|
#include <libeval_compiler/libeval_compiler.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,12 +34,6 @@ class BOARD_ITEM;
|
||||||
class PCB_EXPR_UCODE;
|
class PCB_EXPR_UCODE;
|
||||||
|
|
||||||
|
|
||||||
#define CLEARANCE_CONSTRAINT (1 << 0)
|
|
||||||
#define ANNULUS_CONSTRAINT (1 << 1)
|
|
||||||
#define TRACK_CONSTRAINT (1 << 2)
|
|
||||||
#define HOLE_CONSTRAINT (1 << 3)
|
|
||||||
#define DISALLOW_CONSTRAINT (1 << 4)
|
|
||||||
|
|
||||||
#define DISALLOW_VIAS (1 << 0)
|
#define DISALLOW_VIAS (1 << 0)
|
||||||
#define DISALLOW_MICRO_VIAS (1 << 1)
|
#define DISALLOW_MICRO_VIAS (1 << 1)
|
||||||
#define DISALLOW_BB_VIAS (1 << 2)
|
#define DISALLOW_BB_VIAS (1 << 2)
|
||||||
|
@ -52,6 +46,17 @@ class PCB_EXPR_UCODE;
|
||||||
#define DISALLOW_FOOTPRINTS (1 << 9)
|
#define DISALLOW_FOOTPRINTS (1 << 9)
|
||||||
|
|
||||||
|
|
||||||
|
enum DRC_RULE_ID_T
|
||||||
|
{
|
||||||
|
DRC_RULE_ID_UNKNOWN = -1,
|
||||||
|
DRC_RULE_ID_CLEARANCE = 0,
|
||||||
|
DRC_RULE_ID_HOLE_SIZE,
|
||||||
|
DRC_RULE_ID_ANNULUS,
|
||||||
|
DRC_RULE_ID_TRACK,
|
||||||
|
DRC_RULE_ID_DISALLOW
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template<class T=int>
|
template<class T=int>
|
||||||
class MINOPTMAX
|
class MINOPTMAX
|
||||||
{
|
{
|
||||||
|
@ -78,19 +83,36 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DRC_CONSTRAINT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DRC_CONSTRAINT() :
|
||||||
|
m_Type( DRC_RULE_ID_UNKNOWN ),
|
||||||
|
m_DisallowFlags( 0 ),
|
||||||
|
m_LayerCondition( LSET::AllLayersMask() )
|
||||||
|
{}
|
||||||
|
|
||||||
|
const MINOPTMAX<int>& GetValue() const { return m_Value; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
DRC_RULE_ID_T m_Type;
|
||||||
|
MINOPTMAX<int> m_Value;
|
||||||
|
int m_DisallowFlags;
|
||||||
|
LSET m_LayerCondition;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class DRC_RULE_CONDITION
|
class DRC_RULE_CONDITION
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DRC_RULE_CONDITION();
|
DRC_RULE_CONDITION();
|
||||||
~DRC_RULE_CONDITION();
|
~DRC_RULE_CONDITION();
|
||||||
|
|
||||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
|
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer );
|
||||||
bool Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset );
|
bool Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LSET m_LayerCondition;
|
|
||||||
wxString m_Expression;
|
wxString m_Expression;
|
||||||
wxString m_TargetRuleName;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PCB_EXPR_UCODE* m_ucode;
|
PCB_EXPR_UCODE* m_ucode;
|
||||||
|
@ -100,40 +122,20 @@ private:
|
||||||
class DRC_RULE
|
class DRC_RULE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DRC_RULE() :
|
DRC_RULE();
|
||||||
m_ConstraintFlags( 0 ),
|
virtual ~DRC_RULE();
|
||||||
m_DisallowFlags( 0 ),
|
|
||||||
m_Clearance( { 0, 0, INT_MAX / 2 } ),
|
|
||||||
m_MinAnnulusWidth( 0 ),
|
|
||||||
m_TrackConstraint( { 0, 0, INT_MAX / 2 } ),
|
|
||||||
m_MinHole( 0 )
|
|
||||||
{ }
|
|
||||||
|
|
||||||
struct MINOPTMAX
|
|
||||||
{
|
|
||||||
int Min;
|
|
||||||
int Opt;
|
|
||||||
int Max;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxString m_Name;
|
wxString m_Name;
|
||||||
int m_ConstraintFlags;
|
LSET m_LayerCondition;
|
||||||
int m_DisallowFlags;
|
wxString m_TestProviderName;
|
||||||
|
DRC_RULE_CONDITION m_Condition;
|
||||||
// A 0 value means the property is not modified by this rule.
|
std::vector<DRC_CONSTRAINT> m_Constraints;
|
||||||
// A positive value is a minimum.
|
|
||||||
MINOPTMAX m_Clearance;
|
|
||||||
int m_MinAnnulusWidth;
|
|
||||||
MINOPTMAX m_TrackConstraint;
|
|
||||||
int m_MinHole;
|
|
||||||
|
|
||||||
LSET m_LayerCondition;
|
|
||||||
DRC_RULE_CONDITION m_Condition;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint );
|
const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
|
||||||
|
int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName );
|
||||||
|
|
||||||
|
|
||||||
#endif // DRC_RULE_H
|
#endif // DRC_RULE_H
|
||||||
|
|
|
@ -178,49 +178,6 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
||||||
|
|
||||||
switch( token )
|
switch( token )
|
||||||
{
|
{
|
||||||
case T_disallow:
|
|
||||||
token = NextTok();
|
|
||||||
|
|
||||||
if( (int) token == DSN_RIGHT )
|
|
||||||
{
|
|
||||||
reportError( _( "Missing disallowed type.| Expected 'track', 'via', 'micro_via', "
|
|
||||||
"'blind_via', 'pad', 'zone', 'text', 'graphic' or 'hole'." ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if( (int) token == DSN_STRING )
|
|
||||||
{
|
|
||||||
token = GetCurStrAsToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch( token )
|
|
||||||
{
|
|
||||||
case T_track: rule->m_DisallowFlags |= DISALLOW_TRACKS; break;
|
|
||||||
case T_via: rule->m_DisallowFlags |= DISALLOW_VIAS; break;
|
|
||||||
case T_micro_via: rule->m_DisallowFlags |= DISALLOW_MICRO_VIAS; break;
|
|
||||||
case T_buried_via: rule->m_DisallowFlags |= DISALLOW_BB_VIAS; break;
|
|
||||||
case T_pad: rule->m_DisallowFlags |= DISALLOW_PADS; break;
|
|
||||||
case T_zone: rule->m_DisallowFlags |= DISALLOW_ZONES; break;
|
|
||||||
case T_text: rule->m_DisallowFlags |= DISALLOW_TEXTS; break;
|
|
||||||
case T_graphic: rule->m_DisallowFlags |= DISALLOW_GRAPHICS; break;
|
|
||||||
case T_hole: rule->m_DisallowFlags |= DISALLOW_HOLES; break;
|
|
||||||
case T_footprint: rule->m_DisallowFlags |= DISALLOW_FOOTPRINTS; break;
|
|
||||||
default:
|
|
||||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'track', 'via', 'micro_via', "
|
|
||||||
"'blind_via', 'pad', 'zone', 'text', 'graphic' or 'hole'." ),
|
|
||||||
FromUTF8() );
|
|
||||||
reportError( msg );
|
|
||||||
}
|
|
||||||
|
|
||||||
rule->m_ConstraintFlags = DISALLOW_CONSTRAINT;
|
|
||||||
|
|
||||||
if( (int) NextTok() != DSN_RIGHT )
|
|
||||||
{
|
|
||||||
reportError( wxString::Format( _( "Unrecognized item '%s'." ), FromUTF8() ) );
|
|
||||||
parseUnknown();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_constraint:
|
case T_constraint:
|
||||||
parseConstraint( rule );
|
parseConstraint( rule );
|
||||||
break;
|
break;
|
||||||
|
@ -273,34 +230,65 @@ DRC_RULE* DRC_RULES_PARSER::parseDRC_RULE()
|
||||||
|
|
||||||
void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||||
{
|
{
|
||||||
T token;
|
aRule->m_Constraints.emplace_back( DRC_CONSTRAINT() );
|
||||||
int constraintType = 0;
|
|
||||||
int value;
|
|
||||||
wxString msg;
|
|
||||||
|
|
||||||
token = NextTok();
|
DRC_CONSTRAINT& constraint = aRule->m_Constraints.back();
|
||||||
|
int value;
|
||||||
|
wxString msg;
|
||||||
|
|
||||||
|
T token = NextTok();
|
||||||
|
|
||||||
if( (int) token == DSN_RIGHT )
|
if( (int) token == DSN_RIGHT )
|
||||||
{
|
{
|
||||||
reportError( _( "Missing constraint type.| Expected 'clearance', 'track_width', "
|
reportError( _( "Missing constraint type.| Expected 'clearance', 'track_width', "
|
||||||
"'annulus_width' or 'hole'." ) );
|
"'annulus_width', 'hole' or 'disallow'." ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( token )
|
switch( token )
|
||||||
{
|
{
|
||||||
case T_clearance: constraintType = CLEARANCE_CONSTRAINT; break;
|
case T_clearance: constraint.m_Type = DRC_RULE_ID_CLEARANCE; break;
|
||||||
case T_track_width: constraintType = TRACK_CONSTRAINT; break;
|
case T_track_width: constraint.m_Type = DRC_RULE_ID_TRACK; break;
|
||||||
case T_annulus_width: constraintType = ANNULUS_CONSTRAINT; break;
|
case T_annulus_width: constraint.m_Type = DRC_RULE_ID_ANNULUS; break;
|
||||||
case T_hole: constraintType = HOLE_CONSTRAINT; break;
|
case T_hole: constraint.m_Type = DRC_RULE_ID_HOLE_SIZE; break;
|
||||||
|
case T_disallow: constraint.m_Type = DRC_RULE_ID_DISALLOW; break;
|
||||||
default:
|
default:
|
||||||
msg.Printf( _( "Unrecognized item '%s'.| Expected 'clearance', 'track_width', "
|
msg.Printf( _( "Unrecognized item '%s'.| Expected 'clearance', 'track_width', "
|
||||||
"'annulus_width' or 'hole'." ),
|
"'annulus_width', 'hole' or 'disallow'." ),
|
||||||
FromUTF8() );
|
FromUTF8() );
|
||||||
reportError( msg );
|
reportError( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
aRule->m_ConstraintFlags |= constraintType;
|
if( constraint.m_Type == DRC_RULE_ID_DISALLOW )
|
||||||
|
{
|
||||||
|
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||||
|
{
|
||||||
|
if( (int) token == DSN_STRING )
|
||||||
|
token = GetCurStrAsToken();
|
||||||
|
|
||||||
|
switch( token )
|
||||||
|
{
|
||||||
|
case T_track: constraint.m_DisallowFlags |= DISALLOW_TRACKS; break;
|
||||||
|
case T_via: constraint.m_DisallowFlags |= DISALLOW_VIAS; break;
|
||||||
|
case T_micro_via: constraint.m_DisallowFlags |= DISALLOW_MICRO_VIAS; break;
|
||||||
|
case T_buried_via: constraint.m_DisallowFlags |= DISALLOW_BB_VIAS; break;
|
||||||
|
case T_pad: constraint.m_DisallowFlags |= DISALLOW_PADS; break;
|
||||||
|
case T_zone: constraint.m_DisallowFlags |= DISALLOW_ZONES; break;
|
||||||
|
case T_text: constraint.m_DisallowFlags |= DISALLOW_TEXTS; break;
|
||||||
|
case T_graphic: constraint.m_DisallowFlags |= DISALLOW_GRAPHICS; break;
|
||||||
|
case T_hole: constraint.m_DisallowFlags |= DISALLOW_HOLES; break;
|
||||||
|
case T_footprint: constraint.m_DisallowFlags |= DISALLOW_FOOTPRINTS; break;
|
||||||
|
default:
|
||||||
|
msg.Printf( _( "Unrecognized item '%s'.| Expected 'track', 'via', 'micro_via', "
|
||||||
|
"'blind_via', 'pad', 'zone', 'text', 'graphic' or 'hole'." ),
|
||||||
|
FromUTF8() );
|
||||||
|
reportError( msg );
|
||||||
|
parseUnknown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||||
{
|
{
|
||||||
|
@ -321,14 +309,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||||
}
|
}
|
||||||
|
|
||||||
parseValueWithUnits( FromUTF8(), value );
|
parseValueWithUnits( FromUTF8(), value );
|
||||||
|
constraint.m_Value.SetMin( value );
|
||||||
switch( constraintType )
|
|
||||||
{
|
|
||||||
case CLEARANCE_CONSTRAINT: aRule->m_Clearance.Min = value; break;
|
|
||||||
case TRACK_CONSTRAINT: aRule->m_TrackConstraint.Min = value; break;
|
|
||||||
case ANNULUS_CONSTRAINT: aRule->m_MinAnnulusWidth = value; break;
|
|
||||||
case HOLE_CONSTRAINT: aRule->m_MinHole = value; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (int) NextTok() != DSN_RIGHT )
|
if( (int) NextTok() != DSN_RIGHT )
|
||||||
{
|
{
|
||||||
|
@ -348,12 +329,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||||
}
|
}
|
||||||
|
|
||||||
parseValueWithUnits( FromUTF8(), value );
|
parseValueWithUnits( FromUTF8(), value );
|
||||||
|
constraint.m_Value.SetMax( value );
|
||||||
switch( constraintType )
|
|
||||||
{
|
|
||||||
case CLEARANCE_CONSTRAINT: aRule->m_Clearance.Max = value; break;
|
|
||||||
case TRACK_CONSTRAINT: aRule->m_TrackConstraint.Max = value; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (int) NextTok() != DSN_RIGHT )
|
if( (int) NextTok() != DSN_RIGHT )
|
||||||
{
|
{
|
||||||
|
@ -373,12 +349,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||||
}
|
}
|
||||||
|
|
||||||
parseValueWithUnits( FromUTF8(), value );
|
parseValueWithUnits( FromUTF8(), value );
|
||||||
|
constraint.m_Value.SetOpt( value );
|
||||||
switch( constraintType )
|
|
||||||
{
|
|
||||||
case CLEARANCE_CONSTRAINT: aRule->m_Clearance.Opt = value; break;
|
|
||||||
case TRACK_CONSTRAINT: aRule->m_TrackConstraint.Opt = value; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (int) NextTok() != DSN_RIGHT )
|
if( (int) NextTok() != DSN_RIGHT )
|
||||||
{
|
{
|
||||||
|
|
|
@ -468,13 +468,17 @@ void GERBER_JOBFILE_WRITER::addJSONDesignRules()
|
||||||
|
|
||||||
for( MODULE* module : m_pcb->Modules() )
|
for( MODULE* module : m_pcb->Modules() )
|
||||||
{
|
{
|
||||||
for( auto& pad : module->Pads() )
|
for( D_PAD* pad : module->Pads() )
|
||||||
{
|
{
|
||||||
if( ( pad->GetLayerSet() & LSET::InternalCuMask() ).any() )
|
for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() )
|
||||||
minPadClearanceInner = std::min( minPadClearanceInner, pad->GetClearance() );
|
{
|
||||||
|
int padClearance = pad->GetClearance( layer );
|
||||||
|
|
||||||
if( ( pad->GetLayerSet() & LSET::ExternalCuMask() ).any() )
|
if( layer == B_Cu || layer == F_Cu )
|
||||||
minPadClearanceOuter = std::min( minPadClearanceOuter, pad->GetClearance() );
|
minPadClearanceOuter = std::min( minPadClearanceOuter, padClearance );
|
||||||
|
else
|
||||||
|
minPadClearanceInner = std::min( minPadClearanceInner, padClearance );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,12 +523,15 @@ void GERBER_JOBFILE_WRITER::addJSONDesignRules()
|
||||||
if( zone->GetIsKeepout() || !zone->IsOnCopperLayer() )
|
if( zone->GetIsKeepout() || !zone->IsOnCopperLayer() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int zclerance = zone->GetClearance();
|
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||||
|
{
|
||||||
|
int zclerance = zone->GetClearance( layer );
|
||||||
|
|
||||||
if( zone->GetLayer() == B_Cu || zone->GetLayer() == F_Cu )
|
if( layer == B_Cu || layer == F_Cu )
|
||||||
minclearanceOuter = std::min( minclearanceOuter, zclerance );
|
minclearanceOuter = std::min( minclearanceOuter, zclerance );
|
||||||
else
|
else
|
||||||
minclearanceInner = std::min( minclearanceInner, zclerance );
|
minclearanceInner = std::min( minclearanceInner, zclerance );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( minclearanceOuter != INT_MAX )
|
if( minclearanceOuter != INT_MAX )
|
||||||
|
|
|
@ -140,6 +140,63 @@ static void insideCourtyard( LIBEVAL::CONTEXT* aCtx, void* self )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
||||||
|
{
|
||||||
|
PCB_EXPR_CONTEXT* context = static_cast<PCB_EXPR_CONTEXT*>( aCtx );
|
||||||
|
LIBEVAL::VALUE* arg = aCtx->Pop();
|
||||||
|
LIBEVAL::VALUE* result = aCtx->AllocValue();
|
||||||
|
|
||||||
|
result->Set( 0.0 );
|
||||||
|
aCtx->Push( result );
|
||||||
|
|
||||||
|
if( !arg )
|
||||||
|
{
|
||||||
|
aCtx->ReportError( wxString::Format( _( "Missing argument to '%s'" ),
|
||||||
|
wxT( "insideArea()" ) ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PCB_EXPR_VAR_REF* vref = static_cast<PCB_EXPR_VAR_REF*>( self );
|
||||||
|
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||||
|
ZONE_CONTAINER* zone = nullptr;
|
||||||
|
|
||||||
|
if( !item )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( arg->AsString() == "A" )
|
||||||
|
{
|
||||||
|
zone = dynamic_cast<ZONE_CONTAINER*>( context->GetItem( 0 ) );
|
||||||
|
}
|
||||||
|
else if( arg->AsString() == "B" )
|
||||||
|
{
|
||||||
|
zone = dynamic_cast<ZONE_CONTAINER*>( context->GetItem( 1 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( ZONE_CONTAINER* candidate : item->GetBoard()->Zones() )
|
||||||
|
{
|
||||||
|
if( candidate->GetZoneName().Matches( arg->AsString() ) )
|
||||||
|
{
|
||||||
|
zone = candidate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( zone )
|
||||||
|
{
|
||||||
|
SHAPE_POLY_SET zonePoly = zone->GetFilledPolysList( context->GetLayer() );
|
||||||
|
SHAPE_POLY_SET testPoly;
|
||||||
|
|
||||||
|
item->TransformShapeWithClearanceToPolygon( testPoly, 0 );
|
||||||
|
testPoly.BooleanIntersection( zonePoly, SHAPE_POLY_SET::PM_FAST );
|
||||||
|
|
||||||
|
if( testPoly.OutlineCount() )
|
||||||
|
result->Set( 1.0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS()
|
PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS()
|
||||||
{
|
{
|
||||||
auto registerFunc = [&]( const wxString& funcSignature, FPTR funcPtr )
|
auto registerFunc = [&]( const wxString& funcSignature, FPTR funcPtr )
|
||||||
|
@ -152,6 +209,7 @@ PCB_EXPR_BUILTIN_FUNCTIONS::PCB_EXPR_BUILTIN_FUNCTIONS()
|
||||||
registerFunc( "onLayer('x')", onLayer );
|
registerFunc( "onLayer('x')", onLayer );
|
||||||
registerFunc( "isPlated()", isPlated );
|
registerFunc( "isPlated()", isPlated );
|
||||||
registerFunc( "insideCourtyard('x')", insideCourtyard );
|
registerFunc( "insideCourtyard('x')", insideCourtyard );
|
||||||
|
registerFunc( "insideArea('x')", insideArea );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,8 @@ public:
|
||||||
class PCB_EXPR_CONTEXT : public LIBEVAL::CONTEXT
|
class PCB_EXPR_CONTEXT : public LIBEVAL::CONTEXT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PCB_EXPR_CONTEXT()
|
PCB_EXPR_CONTEXT( PCB_LAYER_ID aLayer ) :
|
||||||
|
m_layer( aLayer )
|
||||||
{
|
{
|
||||||
m_items[0] = nullptr;
|
m_items[0] = nullptr;
|
||||||
m_items[1] = nullptr;
|
m_items[1] = nullptr;
|
||||||
|
@ -69,8 +70,14 @@ public:
|
||||||
return m_items[index];
|
return m_items[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCB_LAYER_ID GetLayer() const
|
||||||
|
{
|
||||||
|
return m_layer;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BOARD_ITEM* m_items[2];
|
BOARD_ITEM* m_items[2];
|
||||||
|
PCB_LAYER_ID m_layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -508,7 +508,8 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer )
|
||||||
m_gal->SetIsFill( false );
|
m_gal->SetIsFill( false );
|
||||||
m_gal->SetIsStroke( true );
|
m_gal->SetIsStroke( true );
|
||||||
m_gal->SetStrokeColor( color );
|
m_gal->SetStrokeColor( color );
|
||||||
m_gal->DrawSegment( start, end, width + aTrack->GetClearance() * 2 );
|
m_gal->DrawSegment( start, end,
|
||||||
|
width + aTrack->GetClearance( ToLAYER_ID( aLayer ) ) * 2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,7 +548,7 @@ void PCB_PAINTER::draw( const ARC* aArc, int aLayer )
|
||||||
m_gal->SetStrokeColor( color );
|
m_gal->SetStrokeColor( color );
|
||||||
|
|
||||||
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
|
m_gal->DrawArcSegment( center, radius, start_angle, start_angle + angle,
|
||||||
width + aArc->GetClearance() * 2 );
|
width + aArc->GetClearance( ToLAYER_ID( aLayer ) ) * 2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,7 +689,7 @@ void PCB_PAINTER::draw( const VIA* aVia, int aLayer )
|
||||||
m_gal->SetIsFill( false );
|
m_gal->SetIsFill( false );
|
||||||
m_gal->SetIsStroke( true );
|
m_gal->SetIsStroke( true );
|
||||||
m_gal->SetStrokeColor( color );
|
m_gal->SetStrokeColor( color );
|
||||||
m_gal->DrawCircle( center, radius + aVia->GetClearance() );
|
m_gal->DrawCircle( center, radius + aVia->GetClearance( aVia->GetLayer() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,7 +895,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
|
||||||
m_gal->SetIsStroke( true );
|
m_gal->SetIsStroke( true );
|
||||||
m_gal->SetIsFill( false );
|
m_gal->SetIsFill( false );
|
||||||
m_gal->SetStrokeColor( color );
|
m_gal->SetStrokeColor( color );
|
||||||
int clearance = aPad->GetClearance();
|
int clearance = aPad->GetClearance( aPad->GetLayer() );
|
||||||
|
|
||||||
const std::shared_ptr<SHAPE_COMPOUND> shapes =
|
const std::shared_ptr<SHAPE_COMPOUND> shapes =
|
||||||
std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
|
std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
|
||||||
|
|
|
@ -1750,9 +1750,10 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
||||||
if( !(item->GetLayerSet() & lset ).any() )
|
if( !(item->GetLayerSet() & lset ).any() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( auto track = dyn_cast<TRACK*>( item ) )
|
if( TRACK* track = dyn_cast<TRACK*>( item ) )
|
||||||
{
|
{
|
||||||
int max_clearance = std::max( clearance, track->GetClearance() );
|
int max_clearance = std::max( clearance,
|
||||||
|
track->GetClearance( track->GetLayer() ) );
|
||||||
|
|
||||||
if( TestSegmentHit( position, track->GetStart(), track->GetEnd(),
|
if( TestSegmentHit( position, track->GetStart(), track->GetEnd(),
|
||||||
( track->GetWidth() + aVia->GetWidth() ) / 2 + max_clearance ) )
|
( track->GetWidth() + aVia->GetWidth() ) / 2 + max_clearance ) )
|
||||||
|
@ -1761,11 +1762,11 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
net = track->GetNetCode();
|
net = track->GetNetCode();
|
||||||
clearance = track->GetClearance();
|
clearance = track->GetClearance( track->GetLayer() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( auto via = dyn_cast<VIA*>( item ) )
|
if( VIA* via = dyn_cast<VIA*>( item ) )
|
||||||
{
|
{
|
||||||
int dist = KiROUND( GetLineLength( position, via->GetPosition() ) );
|
int dist = KiROUND( GetLineLength( position, via->GetPosition() ) );
|
||||||
|
|
||||||
|
@ -1773,27 +1774,30 @@ int DRAWING_TOOL::DrawVia( const TOOL_EVENT& aEvent )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( auto mod = dyn_cast<MODULE*>( item ) )
|
if( MODULE* mod = dyn_cast<MODULE*>( item ) )
|
||||||
{
|
{
|
||||||
for( D_PAD* pad : mod->Pads() )
|
for( D_PAD* pad : mod->Pads() )
|
||||||
{
|
{
|
||||||
int max_clearance = std::max( clearance, pad->GetClearance() );
|
for( PCB_LAYER_ID layer : pad->GetLayerSet().Seq() )
|
||||||
|
|
||||||
if( pad->HitTest( aVia->GetBoundingBox(), false, max_clearance ) )
|
|
||||||
{
|
{
|
||||||
if( net && pad->GetNetCode() != net )
|
int max_clearance = std::max( clearance, pad->GetClearance( layer ) );
|
||||||
return true;
|
|
||||||
|
|
||||||
net = pad->GetNetCode();
|
if( pad->HitTest( aVia->GetBoundingBox(), false, max_clearance ) )
|
||||||
clearance = pad->GetClearance();
|
{
|
||||||
}
|
if( net && pad->GetNetCode() != net )
|
||||||
|
return true;
|
||||||
|
|
||||||
if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
net = pad->GetNetCode();
|
||||||
{
|
clearance = pad->GetClearance( layer );
|
||||||
int dist = KiROUND( GetLineLength( position, pad->GetPosition() ) );
|
}
|
||||||
|
|
||||||
if( dist < drillRadius + pad->GetDrillSize().x / 2 + holeToHoleMin )
|
if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||||
return true;
|
{
|
||||||
|
int dist = KiROUND( GetLineLength( position, pad->GetPosition() ) );
|
||||||
|
|
||||||
|
if( dist < drillRadius + pad->GetDrillSize().x / 2 + holeToHoleMin )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,7 +656,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
||||||
if( pad->GetNetCode() > 0 && pad->GetNetCode() == aZone->GetNetCode() )
|
if( pad->GetNetCode() > 0 && pad->GetNetCode() == aZone->GetNetCode() )
|
||||||
gap = std::max( zone_clearance, aZone->GetThermalReliefGap( pad ) );
|
gap = std::max( zone_clearance, aZone->GetThermalReliefGap( pad ) );
|
||||||
else
|
else
|
||||||
gap = aZone->GetClearance( pad );
|
gap = aZone->GetClearance( aLayer, pad );
|
||||||
|
|
||||||
addKnockout( pad, gap, aHoles );
|
addKnockout( pad, gap, aHoles );
|
||||||
}
|
}
|
||||||
|
@ -676,7 +676,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
||||||
|
|
||||||
if( track->GetBoundingBox().Intersects( zone_boundingbox ) )
|
if( track->GetBoundingBox().Intersects( zone_boundingbox ) )
|
||||||
{
|
{
|
||||||
int gap = aZone->GetClearance( track ) + extra_margin;
|
int gap = aZone->GetClearance( aLayer, track ) + extra_margin;
|
||||||
|
|
||||||
track->TransformShapeWithClearanceToPolygon( aHoles, gap, m_low_def );
|
track->TransformShapeWithClearanceToPolygon( aHoles, gap, m_low_def );
|
||||||
}
|
}
|
||||||
|
@ -695,7 +695,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
||||||
if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
|
if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
|
||||||
{
|
{
|
||||||
bool ignoreLineWidth = aItem->IsOnLayer( Edge_Cuts );
|
bool ignoreLineWidth = aItem->IsOnLayer( Edge_Cuts );
|
||||||
int gap = aZone->GetClearance( aItem );
|
int gap = aZone->GetClearance( aLayer, aItem );
|
||||||
|
|
||||||
addKnockout( aItem, gap, ignoreLineWidth, aHoles );
|
addKnockout( aItem, gap, ignoreLineWidth, aHoles );
|
||||||
}
|
}
|
||||||
|
@ -739,7 +739,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
||||||
int gap = 0;
|
int gap = 0;
|
||||||
|
|
||||||
if( !zone->GetIsKeepout() && aZone->GetNetCode() != zone->GetNetCode() )
|
if( !zone->GetIsKeepout() && aZone->GetNetCode() != zone->GetNetCode() )
|
||||||
gap = aZone->GetClearance( zone );
|
gap = aZone->GetClearance( aLayer, zone );
|
||||||
|
|
||||||
zone->TransformOutlinesShapeWithClearanceToPolygon( aHoles, gap );
|
zone->TransformOutlinesShapeWithClearanceToPolygon( aHoles, gap );
|
||||||
}
|
}
|
||||||
|
|
|
@ -536,8 +536,7 @@ void DRC::testPadClearances( BOARD_COMMIT& aCommit )
|
||||||
static DRAWSEGMENT dummyEdge;
|
static DRAWSEGMENT dummyEdge;
|
||||||
dummyEdge.SetLayer( Edge_Cuts );
|
dummyEdge.SetLayer( Edge_Cuts );
|
||||||
|
|
||||||
if( pad->GetRuleClearance( &dummyEdge, &minClearance, &m_clearanceSource ) )
|
pad->GetRuleClearance( &dummyEdge, pad->GetLayer(), &minClearance, &m_clearanceSource );
|
||||||
/* minClearance and m_clearanceSource set in GetRuleClearance() */;
|
|
||||||
|
|
||||||
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
|
||||||
{
|
{
|
||||||
|
|
|
@ -391,7 +391,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
|
||||||
dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
|
dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
|
||||||
|
|
||||||
int minClearance;
|
int minClearance;
|
||||||
DRC_RULE* rule = GetRule( aRefSeg, &dummypad, CLEARANCE_CONSTRAINT );
|
DRC_RULE* rule = GetRule( aRefSeg, &dummypad, DRC_RULE_ID_CLEARANCE );
|
||||||
|
|
||||||
if( rule )
|
if( rule )
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,7 +93,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkPad( D_PAD* aPad )
|
||||||
{
|
{
|
||||||
int minHole = bds.m_MinThroughDrill;
|
int minHole = bds.m_MinThroughDrill;
|
||||||
wxString minHoleSource = _( "board minimum" );
|
wxString minHoleSource = _( "board minimum" );
|
||||||
DRC_RULE* rule = GetRule( aPad, nullptr, HOLE_CONSTRAINT );
|
DRC_RULE* rule = GetRule( aPad, nullptr, DRC_RULE_ID_HOLE_SIZE );
|
||||||
|
|
||||||
if( rule )
|
if( rule )
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkVia( VIA* via )
|
||||||
{
|
{
|
||||||
int minHole = bds.m_MinThroughDrill;
|
int minHole = bds.m_MinThroughDrill;
|
||||||
wxString minHoleSource = _( "board minimum" );
|
wxString minHoleSource = _( "board minimum" );
|
||||||
DRC_RULE* rule = GetRule( via, nullptr, HOLE_CONSTRAINT );
|
DRC_RULE* rule = GetRule( via, nullptr, DRC_RULE_ID_HOLE_SIZE );
|
||||||
|
|
||||||
if( rule )
|
if( rule )
|
||||||
{
|
{
|
||||||
|
@ -179,7 +179,7 @@ bool DRC_DRILLED_HOLE_TESTER::checkMicroVia( VIA* via )
|
||||||
{
|
{
|
||||||
int minHole = bds.m_MicroViasMinDrill;
|
int minHole = bds.m_MicroViasMinDrill;
|
||||||
wxString minHoleSource = _( "board minimum" );
|
wxString minHoleSource = _( "board minimum" );
|
||||||
DRC_RULE* rule = GetRule( via, nullptr, HOLE_CONSTRAINT );
|
DRC_RULE* rule = GetRule( via, nullptr, DRC_RULE_ID_HOLE_SIZE );
|
||||||
|
|
||||||
if( rule )
|
if( rule )
|
||||||
{
|
{
|
||||||
|
|
|
@ -245,7 +245,7 @@ test::DRC_RULE* test::DRC_ENGINE::EvalRulesForItems( test::DRC_RULE_ID_T ruleID,
|
||||||
drc_dbg( 8, " -> check condition '%s'\n",
|
drc_dbg( 8, " -> check condition '%s'\n",
|
||||||
(const char*) condition->m_Expression.c_str() );
|
(const char*) condition->m_Expression.c_str() );
|
||||||
|
|
||||||
bool result = condition->EvaluateFor( a, b );
|
bool result = condition->EvaluateFor( a, b, F_Cu ); // FIXME: need the actual layer
|
||||||
if( result )
|
if( result )
|
||||||
{
|
{
|
||||||
drc_dbg( 8, " -> rule '%s' matches, triggered by condition '%s'\n",
|
drc_dbg( 8, " -> rule '%s' matches, triggered by condition '%s'\n",
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
#include <class_board_item.h>
|
#include <class_board_item.h>
|
||||||
|
|
||||||
|
|
||||||
#include <drc_proto/drc_rule.h>
|
#include <drc_proto/drc_rule.h>
|
||||||
#include <pcb_expr_evaluator.h>
|
#include <pcb_expr_evaluator.h>
|
||||||
|
|
||||||
|
@ -37,14 +36,14 @@ test::DRC_RULE::DRC_RULE() :
|
||||||
m_Conditional( false ),
|
m_Conditional( false ),
|
||||||
m_Priority( 0 )
|
m_Priority( 0 )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
test::DRC_RULE::~DRC_RULE()
|
test::DRC_RULE::~DRC_RULE()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
test::DRC_RULE_CONDITION::DRC_RULE_CONDITION()
|
test::DRC_RULE_CONDITION::DRC_RULE_CONDITION()
|
||||||
{
|
{
|
||||||
m_ucode = nullptr;
|
m_ucode = nullptr;
|
||||||
|
@ -57,11 +56,20 @@ test::DRC_RULE_CONDITION::~DRC_RULE_CONDITION()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool test::DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB )
|
bool test::DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB,
|
||||||
|
PCB_LAYER_ID aLayer )
|
||||||
{
|
{
|
||||||
|
// An unconditional rule is always true
|
||||||
|
if( m_Expression.IsEmpty() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// A rule which failed to compile is always false
|
||||||
|
if( !m_ucode )
|
||||||
|
return false;
|
||||||
|
|
||||||
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
|
BOARD_ITEM* a = const_cast<BOARD_ITEM*>( aItemA );
|
||||||
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
|
BOARD_ITEM* b = aItemB ? const_cast<BOARD_ITEM*>( aItemB ) : DELETED_BOARD_ITEM::GetInstance();
|
||||||
PCB_EXPR_CONTEXT ctx;
|
PCB_EXPR_CONTEXT ctx( aLayer );
|
||||||
ctx.SetItems( a, b );
|
ctx.SetItems( a, b );
|
||||||
|
|
||||||
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
|
return m_ucode->Run( &ctx )->AsDouble() != 0.0;
|
||||||
|
@ -75,7 +83,7 @@ bool test::DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, in
|
||||||
if (!m_ucode)
|
if (!m_ucode)
|
||||||
m_ucode = new PCB_EXPR_UCODE;
|
m_ucode = new PCB_EXPR_UCODE;
|
||||||
|
|
||||||
LIBEVAL::CONTEXT preflightContext;
|
PCB_EXPR_CONTEXT preflightContext( F_Cu );
|
||||||
|
|
||||||
bool ok = compiler.Compile( m_Expression.ToUTF8().data(), m_ucode, &preflightContext );
|
bool ok = compiler.Compile( m_Expression.ToUTF8().data(), m_ucode, &preflightContext );
|
||||||
return ok;
|
return ok;
|
||||||
|
|
|
@ -34,7 +34,6 @@ class BOARD_ITEM;
|
||||||
namespace LIBEVAL
|
namespace LIBEVAL
|
||||||
{
|
{
|
||||||
class UCODE;
|
class UCODE;
|
||||||
class ERROR_STATUS;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PCB_EXPR_UCODE;
|
class PCB_EXPR_UCODE;
|
||||||
|
@ -42,14 +41,20 @@ class PCB_EXPR_UCODE;
|
||||||
namespace test
|
namespace test
|
||||||
{
|
{
|
||||||
|
|
||||||
enum class DRC_RULE_ID_T {
|
enum class DRC_RULE_ID_T
|
||||||
|
{
|
||||||
|
DRC_RULE_ID_UNKNOWN = -1,
|
||||||
DRC_RULE_ID_CLEARANCE = 0,
|
DRC_RULE_ID_CLEARANCE = 0,
|
||||||
DRC_RULE_ID_HOLE_CLEARANCE,
|
DRC_RULE_ID_HOLE_CLEARANCE,
|
||||||
DRC_RULE_ID_EDGE_CLEARANCE,
|
DRC_RULE_ID_EDGE_CLEARANCE,
|
||||||
DRC_RULE_ID_HOLE_SIZE
|
DRC_RULE_ID_HOLE_SIZE,
|
||||||
|
DRC_RULE_ID_ANNULUS,
|
||||||
|
DRC_RULE_ID_TRACK,
|
||||||
|
DRC_RULE_ID_DISALLOW
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DRC_RULE_SEVERITY_T {
|
enum class DRC_RULE_SEVERITY_T
|
||||||
|
{
|
||||||
DRC_SEVERITY_IGNORE = 0,
|
DRC_SEVERITY_IGNORE = 0,
|
||||||
DRC_SEVERITY_WARNING,
|
DRC_SEVERITY_WARNING,
|
||||||
DRC_SEVERITY_ERROR
|
DRC_SEVERITY_ERROR
|
||||||
|
@ -80,17 +85,48 @@ private:
|
||||||
bool m_hasMax = false;
|
bool m_hasMax = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DRC_CONSTRAINT
|
class DRC_CONSTRAINT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
DRC_CONSTRAINT() :
|
||||||
|
m_Type( DRC_RULE_ID_T::DRC_RULE_ID_UNKNOWN ),
|
||||||
|
m_DisallowFlags( 0 ),
|
||||||
|
m_LayerCondition( LSET::AllLayersMask() )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const MINOPTMAX<int>& GetValue() const { return m_Value; }
|
const MINOPTMAX<int>& GetValue() const { return m_Value; }
|
||||||
bool Allowed() const { return m_Allow; }
|
bool Allowed() const { return m_Allow; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MINOPTMAX<int> m_Value;
|
DRC_RULE_ID_T m_Type;
|
||||||
bool m_Allow;
|
MINOPTMAX<int> m_Value;
|
||||||
|
int m_DisallowFlags;
|
||||||
|
LSET m_LayerCondition;
|
||||||
|
|
||||||
|
bool m_Allow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DRC_RULE_CONDITION
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DRC_RULE_CONDITION();
|
||||||
|
~DRC_RULE_CONDITION();
|
||||||
|
|
||||||
|
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer );
|
||||||
|
bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
|
||||||
|
|
||||||
|
public:
|
||||||
|
wxString m_Expression;
|
||||||
|
wxString m_TargetRuleName;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PCB_EXPR_UCODE* m_ucode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class DRC_RULE
|
class DRC_RULE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -115,37 +151,23 @@ public:
|
||||||
public:
|
public:
|
||||||
bool m_Unary;
|
bool m_Unary;
|
||||||
|
|
||||||
wxString m_Name;
|
wxString m_Name;
|
||||||
wxString m_TestProviderName;
|
LSET m_LayerCondition;
|
||||||
|
wxString m_TestProviderName;
|
||||||
|
DRC_RULE_CONDITION m_Condition;
|
||||||
|
std::vector<DRC_CONSTRAINT> m_Constraints;
|
||||||
|
|
||||||
DRC_RULE_SEVERITY_T m_Severity;
|
DRC_RULE_SEVERITY_T m_Severity;
|
||||||
bool m_Enabled;
|
bool m_Enabled;
|
||||||
bool m_Conditional;
|
bool m_Conditional;
|
||||||
int m_Priority; // 0 indicates automatic priority generation
|
int m_Priority; // 0 indicates automatic priority generation
|
||||||
|
|
||||||
DRC_CONSTRAINT m_Constraint;
|
DRC_CONSTRAINT m_Constraint; // FIXME: move to m_Constraints
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DRC_RULE_CONDITION
|
//const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
|
||||||
{
|
// int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName );
|
||||||
public:
|
|
||||||
DRC_RULE_CONDITION();
|
|
||||||
~DRC_RULE_CONDITION();
|
|
||||||
|
|
||||||
bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
|
|
||||||
bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
|
|
||||||
|
|
||||||
public:
|
|
||||||
LSET m_LayerCondition;
|
|
||||||
wxString m_Expression;
|
|
||||||
wxString m_TargetRuleName;
|
|
||||||
|
|
||||||
private:
|
|
||||||
PCB_EXPR_UCODE* m_ucode;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint );
|
|
||||||
|
|
||||||
}; // namespace test
|
}; // namespace test
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue