Add implied diffpair netclass rules.

This commit is contained in:
Jeff Young 2020-10-11 11:19:07 +01:00
parent 34f47b3806
commit bcebb19665
2 changed files with 156 additions and 131 deletions

View File

@ -179,118 +179,155 @@ void DRC_ENGINE::loadImplicitRules()
// 3) per-netclass rules // 3) per-netclass rules
std::vector<DRC_RULE*> netclassRules; std::vector<DRC_RULE*> netclassClearanceRules;
std::vector<DRC_RULE*> netclassItemSpecificRules;
auto makeNetclassRule = auto makeNetclassRules =
[&]( const NETCLASSPTR& netclass, bool isDefault ) [&]( const NETCLASSPTR& nc, bool isDefault )
{ {
// Only add constraints for netclass values which are larger than board minimums. // Note: only add constraints for netclass values which are larger than board
// That way board minimums will still enforce a global minimum. // minimums. (This ensures that the board minimums will still enforce a global
// lower bound.)
DRC_RULE* rule = new DRC_RULE; wxString ncName = nc->GetName();
wxString name = netclass->GetName();
rule->m_Name = wxString::Format( _( "netclass '%s'" ), name ); DRC_RULE* rule;
rule->m_Implicit = true; wxString expr;
wxString expr = wxString::Format( "A.NetClass == '%s'", name ); if( nc->GetClearance() > bds.m_MinClearance
DRC_RULE_CONDITION* condition = new DRC_RULE_CONDITION( expr ); || nc->GetTrackWidth() > bds.m_TrackMinWidth )
rule->m_Condition = condition;
netclassRules.push_back( rule );
if( netclass->GetClearance() > bds.m_MinClearance )
{ {
DRC_CONSTRAINT ncClearanceConstraint( DRC_CONSTRAINT_TYPE_CLEARANCE ); rule = new DRC_RULE;
ncClearanceConstraint.Value().SetMin( netclass->GetClearance() ); rule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
rule->AddConstraint( ncClearanceConstraint ); rule->m_Implicit = true;
expr = wxString::Format( "A.NetClass == '%s'",
ncName );
rule->m_Condition = new DRC_RULE_CONDITION( expr );
netclassClearanceRules.push_back( rule );
if( nc->GetClearance() > bds.m_MinClearance )
{
DRC_CONSTRAINT ncClearanceConstraint( DRC_CONSTRAINT_TYPE_CLEARANCE );
ncClearanceConstraint.Value().SetMin( nc->GetClearance() );
rule->AddConstraint( ncClearanceConstraint );
}
if( nc->GetTrackWidth() > bds.m_TrackMinWidth )
{
DRC_CONSTRAINT ncWidthConstraint( DRC_CONSTRAINT_TYPE_TRACK_WIDTH );
ncWidthConstraint.Value().SetMin( nc->GetTrackWidth() );
rule->AddConstraint( ncWidthConstraint );
}
} }
if( netclass->GetTrackWidth() > bds.m_TrackMinWidth ) if( nc->GetDiffPairWidth() || nc->GetDiffPairGap() )
{ {
DRC_CONSTRAINT ncWidthConstraint( DRC_CONSTRAINT_TYPE_TRACK_WIDTH ); rule = new DRC_RULE;
ncWidthConstraint.Value().SetMin( netclass->GetTrackWidth() ); rule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
rule->AddConstraint( ncWidthConstraint ); rule->m_Implicit = true;
expr = wxString::Format( "A.NetClass == '%s' && A.isDiffPair()",
ncName );
rule->m_Condition = new DRC_RULE_CONDITION( expr );
netclassItemSpecificRules.push_back( rule );
if( nc->GetDiffPairWidth() )
{
DRC_CONSTRAINT constraint( DRC_CONSTRAINT_TYPE_TRACK_WIDTH );
constraint.Value().SetMin( nc->GetDiffPairWidth() );
rule->AddConstraint( constraint );
}
if( nc->GetDiffPairGap() )
{
DRC_CONSTRAINT constraint( DRC_CONSTRAINT_TYPE_DIFF_PAIR_GAP );
constraint.Value().SetMin( nc->GetDiffPairGap() );
rule->AddConstraint( constraint );
}
} }
// We need separate rules for micro-vias and other vias because they use the if( nc->GetViaDiameter() > bds.m_ViasMinSize
// same constraints. || nc->GetViaDrill() > bds.m_MinThroughDrill )
//
// Note that since these are unary rules they don't need to be sorted, so we
// add them directly to the current rule set.
rule = new DRC_RULE;
rule->m_Name = wxString::Format( _( "netclass '%s'" ), name );
rule->m_Implicit = true;
expr = wxString::Format( "A.NetClass == '%s' && A.Via_Type != 'micro_via'", name );
condition = new DRC_RULE_CONDITION( expr );
rule->m_Condition = condition;
addRule( rule );
if( netclass->GetViaDiameter() > bds.m_ViasMinSize )
{ {
DRC_CONSTRAINT ncViaDiaConstraint( DRC_CONSTRAINT_TYPE_VIA_DIAMETER ); rule = new DRC_RULE;
ncViaDiaConstraint.Value().SetMin( netclass->GetViaDiameter() ); rule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
rule->AddConstraint( ncViaDiaConstraint ); rule->m_Implicit = true;
expr = wxString::Format( "A.NetClass == '%s' && A.Via_Type != 'micro_via'",
ncName );
rule->m_Condition = new DRC_RULE_CONDITION( expr );
netclassItemSpecificRules.push_back( rule );
if( nc->GetViaDiameter() > bds.m_ViasMinSize )
{
DRC_CONSTRAINT constraint( DRC_CONSTRAINT_TYPE_VIA_DIAMETER );
constraint.Value().SetMin( nc->GetViaDiameter() );
rule->AddConstraint( constraint );
}
if( nc->GetViaDrill() > bds.m_MinThroughDrill )
{
DRC_CONSTRAINT constraint( DRC_CONSTRAINT_TYPE_HOLE_SIZE );
constraint.Value().SetMin( nc->GetViaDrill() );
rule->AddConstraint( constraint );
}
} }
if( netclass->GetViaDrill() > bds.m_MinThroughDrill ) if( nc->GetuViaDiameter() > bds.m_MicroViasMinSize
|| nc->GetuViaDrill() > bds.m_MicroViasMinDrill )
{ {
DRC_CONSTRAINT ncViaDrillConstraint( DRC_CONSTRAINT_TYPE_HOLE_SIZE ); rule = new DRC_RULE;
ncViaDrillConstraint.Value().SetMin( netclass->GetViaDrill() ); rule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
rule->AddConstraint( ncViaDrillConstraint ); rule->m_Implicit = true;
}
rule = new DRC_RULE; expr = wxString::Format( "A.NetClass == '%s' && A.Via_Type == 'micro_via'",
ncName );
rule->m_Condition = new DRC_RULE_CONDITION( expr );
netclassItemSpecificRules.push_back( rule );
rule->m_Name = wxString::Format( _( "netclass '%s'" ), name ); if( nc->GetuViaDiameter() > bds.m_MicroViasMinSize )
rule->m_Implicit = true; {
DRC_CONSTRAINT constraint( DRC_CONSTRAINT_TYPE_VIA_DIAMETER );
constraint.Value().SetMin( nc->GetuViaDiameter() );
rule->AddConstraint( constraint );
}
expr = wxString::Format( "A.NetClass == '%s' && A.Via_Type == 'micro_via'", name ); if( nc->GetuViaDrill() > bds.m_MicroViasMinDrill )
condition = new DRC_RULE_CONDITION( expr ); {
DRC_CONSTRAINT constraint( DRC_CONSTRAINT_TYPE_HOLE_SIZE );
rule->m_Condition = condition; constraint.Value().SetMin( nc->GetuViaDrill() );
addRule( rule ); rule->AddConstraint( constraint );
}
if( netclass->GetuViaDiameter() > bds.m_MicroViasMinSize )
{
DRC_CONSTRAINT ncuViaDiaConstraint( DRC_CONSTRAINT_TYPE_VIA_DIAMETER );
ncuViaDiaConstraint.Value().SetMin( netclass->GetuViaDiameter() );
rule->AddConstraint( ncuViaDiaConstraint );
}
if( netclass->GetuViaDrill() > bds.m_MicroViasMinDrill )
{
DRC_CONSTRAINT ncuViaDrillConstraint( DRC_CONSTRAINT_TYPE_HOLE_SIZE );
ncuViaDrillConstraint.Value().SetMin( netclass->GetuViaDrill() );
rule->AddConstraint( ncuViaDrillConstraint );
} }
}; };
m_board->SynchronizeNetsAndNetClasses(); m_board->SynchronizeNetsAndNetClasses();
makeNetclassRule( bds.GetNetClasses().GetDefault(), true ); makeNetclassRules( bds.GetNetClasses().GetDefault(), true );
for( const std::pair<const wxString, NETCLASSPTR>& netclass : bds.GetNetClasses() ) for( const std::pair<const wxString, NETCLASSPTR>& netclass : bds.GetNetClasses() )
makeNetclassRule( netclass.second, false ); makeNetclassRules( netclass.second, false );
// These have to be sorted by min clearance so the right one fires if 'A' and 'B' belong // The netclass clearance rules have to be sorted by min clearance so the right one fires
// to two different netclasses. // if 'A' and 'B' belong to two different netclasses.
//
// The item-specific netclass rules are all unary, so there's no 'A' vs 'B' issue.
std::sort( netclassRules.begin(), netclassRules.end(), std::sort( netclassClearanceRules.begin(), netclassClearanceRules.end(),
[]( DRC_RULE* lhs, DRC_RULE* rhs ) []( DRC_RULE* lhs, DRC_RULE* rhs )
{ {
return lhs->m_Constraints[0].m_Value.Min() return lhs->m_Constraints[0].m_Value.Min()
< rhs->m_Constraints[0].m_Value.Min(); < rhs->m_Constraints[0].m_Value.Min();
} ); } );
for( DRC_RULE* netclassRule : netclassRules ) for( DRC_RULE* ncRule : netclassClearanceRules )
addRule( netclassRule ); addRule( ncRule );
for( DRC_RULE* ncRule : netclassItemSpecificRules )
addRule( ncRule );
ReportAux( wxString::Format( "Building %d implicit netclass rules", ReportAux( wxString::Format( "Building %d implicit netclass rules",
(int) netclassRules.size() ) ); (int) netclassClearanceRules.size() ) );
} }
static wxString formatConstraint( const DRC_CONSTRAINT& constraint ) static wxString formatConstraint( const DRC_CONSTRAINT& constraint )

View File

@ -246,9 +246,10 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
aConstraint->m_RuleName = hostConstraint.GetName(); aConstraint->m_RuleName = hostConstraint.GetName();
aConstraint->m_Type = aType; aConstraint->m_Type = aType;
return true; return true;
}
return false; default:
return false;
}
} }
@ -256,22 +257,24 @@ int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* a
{ {
PNS::CONSTRAINT constraint; PNS::CONSTRAINT constraint;
bool ok = false; bool ok = false;
int rv; int rv = 0;
if( IsDiffPair( aA, aB ) ) if( IsDiffPair( aA, aB ) )
{ {
// for diff pairs, we use the gap value for shoving/dragging // for diff pairs, we use the gap value for shoving/dragging
ok = QueryConstraint( PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP, aA, aB, aA->Layer(), &constraint ); ok = QueryConstraint( PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP, aA, aB, aA->Layer(),
&constraint );
rv = constraint.m_Value.Opt(); rv = constraint.m_Value.Opt();
printf("QueryDPCL %d\n", rv); printf( "QueryDPCL %d\n", rv );
} }
if( !ok ) if( !ok )
{ {
ok = QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, aA->Layer(), &constraint ); ok = QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, aA->Layer(),
&constraint );
assert( ok ); assert( ok );
rv = constraint.m_Value.Min(); rv = constraint.m_Value.Min();
printf("QueryCL %d\n", rv); printf( "QueryCL %d\n", rv );
} }
assert( ok ); assert( ok );
@ -325,59 +328,45 @@ int PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem )
bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM* aStartItem, int aNet ) bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM* aStartItem, int aNet )
{ {
BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings(); BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
PNS::CONSTRAINT constraint;
int trackWidth = 0; int trackWidth = bds.m_TrackMinWidth;
if( bds.m_UseConnectedTrackWidth && aStartItem != nullptr ) if( bds.m_UseConnectedTrackWidth && aStartItem != nullptr )
{ {
trackWidth = inheritTrackWidth( aStartItem ); trackWidth = inheritTrackWidth( aStartItem );
} }
else if( bds.UseNetClassTrack() && aStartItem ) // netclass value
if( !trackWidth && bds.UseNetClassTrack() && aStartItem ) // netclass value
{ {
PNS::CONSTRAINT constraint; if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, aStartItem, nullptr,
bool ok = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, aStartItem->Layer(), &constraint ) )
aStartItem, nullptr, aStartItem->Layer(),
&constraint );
if( ok )
{ {
trackWidth = constraint.m_Value.HasOpt() ? constraint.m_Value.Opt() trackWidth = constraint.m_Value.OptThenMin();
: constraint.m_Value.Min();
} }
} }
else
if( !trackWidth )
{ {
trackWidth = bds.GetCurrentTrackWidth(); trackWidth = bds.GetCurrentTrackWidth();
} }
aSizes.SetTrackWidth( trackWidth ); aSizes.SetTrackWidth( trackWidth );
int viaDiameter = 0; int viaDiameter = bds.m_ViasMinSize;
int viaDrill = 0; int viaDrill = bds.m_MinThroughDrill;
if( bds.UseNetClassVia() && aStartItem ) // netclass value if( bds.UseNetClassVia() && aStartItem ) // netclass value
{ {
PNS::CONSTRAINT diaConstraint, drillConstraint; if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_DIAMETER, aStartItem,
bool okDia = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_DIAMETER, nullptr, aStartItem->Layer(), &constraint ) )
aStartItem, nullptr, aStartItem->Layer(),
&diaConstraint );
bool okDrill = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_HOLE,
aStartItem, nullptr, aStartItem->Layer(),
&drillConstraint );
if( okDia )
{ {
viaDiameter = diaConstraint.m_Value.HasOpt() ? diaConstraint.m_Value.Opt() viaDiameter = constraint.m_Value.OptThenMin();
: diaConstraint.m_Value.Min();
} }
if( okDrill ) if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_HOLE, aStartItem,
nullptr, aStartItem->Layer(), &constraint ) )
{ {
viaDrill = drillConstraint.m_Value.HasOpt() ? drillConstraint.m_Value.Opt() viaDrill = constraint.m_Value.OptThenMin();
: drillConstraint.m_Value.Min();
} }
} }
else else
@ -389,25 +378,24 @@ bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM*
aSizes.SetViaDiameter( viaDiameter ); aSizes.SetViaDiameter( viaDiameter );
aSizes.SetViaDrill( viaDrill ); aSizes.SetViaDrill( viaDrill );
int diffPairWidth = 0; int diffPairWidth = bds.m_TrackMinWidth;
int diffPairGap = 0; int diffPairGap = bds.m_MinClearance;
int diffPairViaGap = 0; int diffPairViaGap = bds.m_MinClearance;
if( bds.UseNetClassDiffPair() && aStartItem ) if( bds.UseNetClassDiffPair() && aStartItem )
{ {
PNS::CONSTRAINT widthConstraint, gapConstraint; if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, aStartItem,
bool okWidth = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, nullptr, aStartItem->Layer(), &constraint ) )
aStartItem, nullptr, aStartItem->Layer(), {
&widthConstraint ); diffPairWidth = constraint.m_Value.OptThenMin();
bool okGap = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP, }
aStartItem, nullptr, aStartItem->Layer(),
&gapConstraint );
if( okWidth ) if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP, aStartItem,
diffPairWidth = widthConstraint.m_Value.OptThenMin(); nullptr, aStartItem->Layer(), &constraint ) )
{
if( okGap ) diffPairGap = constraint.m_Value.OptThenMin();
diffPairViaGap = diffPairGap = gapConstraint.m_Value.OptThenMin(); diffPairViaGap = constraint.m_Value.OptThenMin();
}
} }
else if( bds.UseCustomDiffPairDimensions() ) else if( bds.UseCustomDiffPairDimensions() )
{ {
@ -416,7 +404,7 @@ bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM*
diffPairViaGap = bds.GetCustomDiffPairViaGap(); diffPairViaGap = bds.GetCustomDiffPairViaGap();
} }
//printf("DPWidth: %d gap %d\n", diffPairWidth, diffPairGap ); //printf( "DPWidth: %d gap %d\n", diffPairWidth, diffPairGap );
aSizes.SetDiffPairWidth( diffPairWidth ); aSizes.SetDiffPairWidth( diffPairWidth );
aSizes.SetDiffPairGap( diffPairGap ); aSizes.SetDiffPairGap( diffPairGap );