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

View File

@ -246,29 +246,32 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
aConstraint->m_RuleName = hostConstraint.GetName();
aConstraint->m_Type = aType;
return true;
}
default:
return false;
}
}
int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB )
{
PNS::CONSTRAINT constraint;
bool ok = false;
int rv;
int rv = 0;
if( IsDiffPair( aA, aB ) )
{
// 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();
printf( "QueryDPCL %d\n", rv );
}
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 );
rv = constraint.m_Value.Min();
printf( "QueryCL %d\n", rv );
@ -326,58 +329,44 @@ int PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem )
bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM* aStartItem, int aNet )
{
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
PNS::CONSTRAINT constraint;
int trackWidth = 0;
int trackWidth = bds.m_TrackMinWidth;
if( bds.m_UseConnectedTrackWidth && aStartItem != nullptr )
{
trackWidth = inheritTrackWidth( aStartItem );
}
if( !trackWidth && bds.UseNetClassTrack() && aStartItem ) // netclass value
else if( bds.UseNetClassTrack() && aStartItem ) // netclass value
{
PNS::CONSTRAINT constraint;
bool ok = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH,
aStartItem, nullptr, aStartItem->Layer(),
&constraint );
if( ok )
if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, aStartItem, nullptr,
aStartItem->Layer(), &constraint ) )
{
trackWidth = constraint.m_Value.HasOpt() ? constraint.m_Value.Opt()
: constraint.m_Value.Min();
trackWidth = constraint.m_Value.OptThenMin();
}
}
if( !trackWidth )
else
{
trackWidth = bds.GetCurrentTrackWidth();
}
aSizes.SetTrackWidth( trackWidth );
int viaDiameter = 0;
int viaDrill = 0;
int viaDiameter = bds.m_ViasMinSize;
int viaDrill = bds.m_MinThroughDrill;
if( bds.UseNetClassVia() && aStartItem ) // netclass value
{
PNS::CONSTRAINT diaConstraint, drillConstraint;
bool okDia = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_DIAMETER,
aStartItem, nullptr, aStartItem->Layer(),
&diaConstraint );
bool okDrill = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_HOLE,
aStartItem, nullptr, aStartItem->Layer(),
&drillConstraint );
if( okDia )
if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_VIA_DIAMETER, aStartItem,
nullptr, aStartItem->Layer(), &constraint ) )
{
viaDiameter = diaConstraint.m_Value.HasOpt() ? diaConstraint.m_Value.Opt()
: diaConstraint.m_Value.Min();
viaDiameter = constraint.m_Value.OptThenMin();
}
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()
: drillConstraint.m_Value.Min();
viaDrill = constraint.m_Value.OptThenMin();
}
}
else
@ -389,25 +378,24 @@ bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM*
aSizes.SetViaDiameter( viaDiameter );
aSizes.SetViaDrill( viaDrill );
int diffPairWidth = 0;
int diffPairGap = 0;
int diffPairViaGap = 0;
int diffPairWidth = bds.m_TrackMinWidth;
int diffPairGap = bds.m_MinClearance;
int diffPairViaGap = bds.m_MinClearance;
if( bds.UseNetClassDiffPair() && aStartItem )
{
PNS::CONSTRAINT widthConstraint, gapConstraint;
bool okWidth = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH,
aStartItem, nullptr, aStartItem->Layer(),
&widthConstraint );
bool okGap = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP,
aStartItem, nullptr, aStartItem->Layer(),
&gapConstraint );
if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, aStartItem,
nullptr, aStartItem->Layer(), &constraint ) )
{
diffPairWidth = constraint.m_Value.OptThenMin();
}
if( okWidth )
diffPairWidth = widthConstraint.m_Value.OptThenMin();
if( okGap )
diffPairViaGap = diffPairGap = gapConstraint.m_Value.OptThenMin();
if( m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP, aStartItem,
nullptr, aStartItem->Layer(), &constraint ) )
{
diffPairGap = constraint.m_Value.OptThenMin();
diffPairViaGap = constraint.m_Value.OptThenMin();
}
}
else if( bds.UseCustomDiffPairDimensions() )
{