Add implied diffpair netclass rules.
This commit is contained in:
parent
34f47b3806
commit
bcebb19665
|
@ -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 );
|
||||
rule->m_Implicit = true;
|
||||
DRC_RULE* rule;
|
||||
wxString expr;
|
||||
|
||||
wxString expr = wxString::Format( "A.NetClass == '%s'", name );
|
||||
DRC_RULE_CONDITION* condition = new DRC_RULE_CONDITION( expr );
|
||||
|
||||
rule->m_Condition = condition;
|
||||
netclassRules.push_back( rule );
|
||||
|
||||
if( netclass->GetClearance() > bds.m_MinClearance )
|
||||
if( nc->GetClearance() > bds.m_MinClearance
|
||||
|| nc->GetTrackWidth() > bds.m_TrackMinWidth )
|
||||
{
|
||||
DRC_CONSTRAINT ncClearanceConstraint( DRC_CONSTRAINT_TYPE_CLEARANCE );
|
||||
ncClearanceConstraint.Value().SetMin( netclass->GetClearance() );
|
||||
rule->AddConstraint( ncClearanceConstraint );
|
||||
rule = new DRC_RULE;
|
||||
rule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
|
||||
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 );
|
||||
ncWidthConstraint.Value().SetMin( netclass->GetTrackWidth() );
|
||||
rule->AddConstraint( ncWidthConstraint );
|
||||
rule = new DRC_RULE;
|
||||
rule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
|
||||
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
|
||||
// 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.
|
||||
|
||||
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 )
|
||||
if( nc->GetViaDiameter() > bds.m_ViasMinSize
|
||||
|| nc->GetViaDrill() > bds.m_MinThroughDrill )
|
||||
{
|
||||
DRC_CONSTRAINT ncViaDiaConstraint( DRC_CONSTRAINT_TYPE_VIA_DIAMETER );
|
||||
ncViaDiaConstraint.Value().SetMin( netclass->GetViaDiameter() );
|
||||
rule->AddConstraint( ncViaDiaConstraint );
|
||||
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->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 );
|
||||
ncViaDrillConstraint.Value().SetMin( netclass->GetViaDrill() );
|
||||
rule->AddConstraint( ncViaDrillConstraint );
|
||||
}
|
||||
rule = new DRC_RULE;
|
||||
rule->m_Name = wxString::Format( _( "netclass '%s'" ), ncName );
|
||||
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 );
|
||||
rule->m_Implicit = true;
|
||||
if( nc->GetuViaDiameter() > bds.m_MicroViasMinSize )
|
||||
{
|
||||
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 );
|
||||
condition = new DRC_RULE_CONDITION( expr );
|
||||
|
||||
rule->m_Condition = condition;
|
||||
addRule( rule );
|
||||
|
||||
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 );
|
||||
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 )
|
||||
|
|
|
@ -246,9 +246,10 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
|
|||
aConstraint->m_RuleName = hostConstraint.GetName();
|
||||
aConstraint->m_Type = aType;
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
printf( "QueryCL %d\n", rv );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
|
@ -416,7 +404,7 @@ bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM*
|
|||
diffPairViaGap = bds.GetCustomDiffPairViaGap();
|
||||
}
|
||||
|
||||
//printf("DPWidth: %d gap %d\n", diffPairWidth, diffPairGap );
|
||||
//printf( "DPWidth: %d gap %d\n", diffPairWidth, diffPairGap );
|
||||
|
||||
aSizes.SetDiffPairWidth( diffPairWidth );
|
||||
aSizes.SetDiffPairGap( diffPairGap );
|
||||
|
|
Loading…
Reference in New Issue