Move diff-pair netname resolution to BOARD.
Also adds reporting of dp gap constaints and max uncoupled to track selections, and max uncoupled during routing. Fixes https://gitlab.com/kicad/code/kicad/-/issues/13748
This commit is contained in:
parent
2c02c26af4
commit
d51e058e24
|
@ -1640,6 +1640,71 @@ NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int BOARD::MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
|
||||||
|
{
|
||||||
|
int rv = 0;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
|
||||||
|
{
|
||||||
|
int ch = *it;
|
||||||
|
|
||||||
|
if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if( ch == '+' )
|
||||||
|
{
|
||||||
|
aComplementNet = wxT( "-" );
|
||||||
|
rv = 1;
|
||||||
|
}
|
||||||
|
else if( ch == '-' )
|
||||||
|
{
|
||||||
|
aComplementNet = wxT( "+" );
|
||||||
|
rv = -1;
|
||||||
|
}
|
||||||
|
else if( ch == 'N' )
|
||||||
|
{
|
||||||
|
aComplementNet = wxT( "P" );
|
||||||
|
rv = -1;
|
||||||
|
}
|
||||||
|
else if ( ch == 'P' )
|
||||||
|
{
|
||||||
|
aComplementNet = wxT( "N" );
|
||||||
|
rv = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rv != 0 && count >= 1 )
|
||||||
|
{
|
||||||
|
aComplementNet = aNetName.Left( aNetName.length() - count )
|
||||||
|
+ aComplementNet
|
||||||
|
+ aNetName.Right( count - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NETINFO_ITEM* BOARD::DpCoupledNet( const NETINFO_ITEM* aNet )
|
||||||
|
{
|
||||||
|
if( aNet )
|
||||||
|
{
|
||||||
|
wxString refName = aNet->GetNetname();
|
||||||
|
wxString coupledNetName;
|
||||||
|
|
||||||
|
if( MatchDpSuffix( refName, coupledNetName ) )
|
||||||
|
return FindNet( coupledNetName );
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
|
FOOTPRINT* BOARD::FindFootprintByReference( const wxString& aReference ) const
|
||||||
{
|
{
|
||||||
for( FOOTPRINT* footprint : m_footprints )
|
for( FOOTPRINT* footprint : m_footprints )
|
||||||
|
|
|
@ -804,6 +804,22 @@ public:
|
||||||
*/
|
*/
|
||||||
NETINFO_ITEM* FindNet( const wxString& aNetname ) const;
|
NETINFO_ITEM* FindNet( const wxString& aNetname ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the coupled netname for a given net.
|
||||||
|
*
|
||||||
|
* This accepts netnames suffixed by 'P', 'N', '+', '-', as well as additional numbers and
|
||||||
|
* underscores following the suffix. So NET_P_123 is a valid positive net name matched to
|
||||||
|
* NET_N_123.
|
||||||
|
*
|
||||||
|
* @return the polarity of the given net (or 0 if it is not a diffpair net).
|
||||||
|
*/
|
||||||
|
int MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the coupled net for a given net. If not a diffpair, nullptr is returned.
|
||||||
|
*/
|
||||||
|
NETINFO_ITEM* DpCoupledNet( const NETINFO_ITEM* aNet );
|
||||||
|
|
||||||
const NETINFO_LIST& GetNetInfo() const
|
const NETINFO_LIST& GetNetInfo() const
|
||||||
{
|
{
|
||||||
return m_NetInfo;
|
return m_NetInfo;
|
||||||
|
|
|
@ -907,7 +907,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
|
||||||
MessageTextFromValue( c->constraint.m_Value.Min() ) ) )
|
MessageTextFromValue( c->constraint.m_Value.Min() ) ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT:
|
case MAX_UNCOUPLED_CONSTRAINT:
|
||||||
REPORT( wxString::Format( _( "Checking %s max uncoupled length: %s." ),
|
REPORT( wxString::Format( _( "Checking %s max uncoupled length: %s." ),
|
||||||
EscapeHTML( c->constraint.GetName() ),
|
EscapeHTML( c->constraint.GetName() ),
|
||||||
MessageTextFromValue( c->constraint.m_Value.Max() ) ) )
|
MessageTextFromValue( c->constraint.m_Value.Max() ) ) )
|
||||||
|
|
|
@ -64,7 +64,7 @@ enum DRC_CONSTRAINT_T
|
||||||
LENGTH_CONSTRAINT,
|
LENGTH_CONSTRAINT,
|
||||||
SKEW_CONSTRAINT,
|
SKEW_CONSTRAINT,
|
||||||
DIFF_PAIR_GAP_CONSTRAINT,
|
DIFF_PAIR_GAP_CONSTRAINT,
|
||||||
DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT,
|
MAX_UNCOUPLED_CONSTRAINT,
|
||||||
DIFF_PAIR_INTRA_SKEW_CONSTRAINT,
|
DIFF_PAIR_INTRA_SKEW_CONSTRAINT,
|
||||||
VIA_COUNT_CONSTRAINT,
|
VIA_COUNT_CONSTRAINT,
|
||||||
PHYSICAL_CLEARANCE_CONSTRAINT,
|
PHYSICAL_CLEARANCE_CONSTRAINT,
|
||||||
|
|
|
@ -325,7 +325,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
|
||||||
case T_skew: c.m_Type = SKEW_CONSTRAINT; break;
|
case T_skew: c.m_Type = SKEW_CONSTRAINT; break;
|
||||||
case T_via_count: c.m_Type = VIA_COUNT_CONSTRAINT; break;
|
case T_via_count: c.m_Type = VIA_COUNT_CONSTRAINT; break;
|
||||||
case T_diff_pair_gap: c.m_Type = DIFF_PAIR_GAP_CONSTRAINT; break;
|
case T_diff_pair_gap: c.m_Type = DIFF_PAIR_GAP_CONSTRAINT; break;
|
||||||
case T_diff_pair_uncoupled: c.m_Type = DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT; break;
|
case T_diff_pair_uncoupled: c.m_Type = MAX_UNCOUPLED_CONSTRAINT; break;
|
||||||
case T_physical_clearance: c.m_Type = PHYSICAL_CLEARANCE_CONSTRAINT; break;
|
case T_physical_clearance: c.m_Type = PHYSICAL_CLEARANCE_CONSTRAINT; break;
|
||||||
case T_physical_hole_clearance: c.m_Type = PHYSICAL_HOLE_CLEARANCE_CONSTRAINT; break;
|
case T_physical_hole_clearance: c.m_Type = PHYSICAL_HOLE_CLEARANCE_CONSTRAINT; break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -297,7 +297,7 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
|
||||||
|
|
||||||
const DRC_CONSTRAINT_T constraintsToCheck[] = {
|
const DRC_CONSTRAINT_T constraintsToCheck[] = {
|
||||||
DIFF_PAIR_GAP_CONSTRAINT,
|
DIFF_PAIR_GAP_CONSTRAINT,
|
||||||
DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT
|
MAX_UNCOUPLED_CONSTRAINT
|
||||||
};
|
};
|
||||||
|
|
||||||
for( int i = 0; i < 2; i++ )
|
for( int i = 0; i < 2; i++ )
|
||||||
|
@ -322,7 +322,7 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
|
||||||
key.gapRuleName = ruleName;
|
key.gapRuleName = ruleName;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT:
|
case MAX_UNCOUPLED_CONSTRAINT:
|
||||||
key.uncoupledConstraint = constraint.GetValue();
|
key.uncoupledConstraint = constraint.GetValue();
|
||||||
key.uncoupledRule = parentRule;
|
key.uncoupledRule = parentRule;
|
||||||
key.uncoupledRuleName = ruleName;
|
key.uncoupledRuleName = ruleName;
|
||||||
|
|
|
@ -363,14 +363,6 @@ static std::string sideToString( const PNS::MEANDER_SIDE aValue )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static NETINFO_ITEM* getCoupledNet( PNS::ROUTER* aRouter, NETINFO_ITEM* aNet )
|
|
||||||
{
|
|
||||||
PNS::RULE_RESOLVER* resolver = aRouter->GetRuleResolver();
|
|
||||||
|
|
||||||
return static_cast<NETINFO_ITEM*>( resolver->DpCoupledNet( aNet ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PCB_GENERATOR_MEANDERS::PCB_GENERATOR_MEANDERS( BOARD_ITEM* aParent, PCB_LAYER_ID aLayer,
|
PCB_GENERATOR_MEANDERS::PCB_GENERATOR_MEANDERS( BOARD_ITEM* aParent, PCB_LAYER_ID aLayer,
|
||||||
LENGTH_TUNING_MODE aMode ) :
|
LENGTH_TUNING_MODE aMode ) :
|
||||||
PCB_GENERATOR( aParent, aLayer ),
|
PCB_GENERATOR( aParent, aLayer ),
|
||||||
|
@ -452,7 +444,7 @@ PCB_GENERATOR_MEANDERS* PCB_GENERATOR_MEANDERS::CreateNew( GENERATOR_TOOL* aTool
|
||||||
DRC_CONSTRAINT constraint;
|
DRC_CONSTRAINT constraint;
|
||||||
PCB_LAYER_ID layer = aStartItem->GetLayer();
|
PCB_LAYER_ID layer = aStartItem->GetLayer();
|
||||||
|
|
||||||
if( aMode == SINGLE && getCoupledNet( aTool->Router(), aStartItem->GetNet() ) )
|
if( aMode == SINGLE && board->DpCoupledNet( aStartItem->GetNet() ) )
|
||||||
aMode = DIFF_PAIR;
|
aMode = DIFF_PAIR;
|
||||||
|
|
||||||
PCB_GENERATOR_MEANDERS* meander = new PCB_GENERATOR_MEANDERS( board, layer, aMode );
|
PCB_GENERATOR_MEANDERS* meander = new PCB_GENERATOR_MEANDERS( board, layer, aMode );
|
||||||
|
@ -543,7 +535,7 @@ void PCB_GENERATOR_MEANDERS::EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NETINFO_ITEM* coupledNet = static_cast<NETINFO_ITEM*>( resolver->DpCoupledNet( net ) );
|
NETINFO_ITEM* coupledNet = aBoard->DpCoupledNet( net );
|
||||||
PNS::SEGMENT coupledItem( m_baseLineCoupled->CSegment( 0 ), coupledNet );
|
PNS::SEGMENT coupledItem( m_baseLineCoupled->CSegment( 0 ), coupledNet );
|
||||||
|
|
||||||
if( m_tuningMode == DIFF_PAIR )
|
if( m_tuningMode == DIFF_PAIR )
|
||||||
|
@ -749,7 +741,7 @@ bool PCB_GENERATOR_MEANDERS::initBaseLines( PNS::ROUTER* aRouter, int aLayer, BO
|
||||||
// DRC rules against.
|
// DRC rules against.
|
||||||
if( m_tuningMode == DIFF_PAIR || m_tuningMode == DIFF_PAIR_SKEW )
|
if( m_tuningMode == DIFF_PAIR || m_tuningMode == DIFF_PAIR_SKEW )
|
||||||
{
|
{
|
||||||
if( NETINFO_ITEM* coupledNet = getCoupledNet( aRouter, net ) )
|
if( NETINFO_ITEM* coupledNet = aBoard->DpCoupledNet( net ) )
|
||||||
{
|
{
|
||||||
VECTOR2I coupledStart = m_origin;
|
VECTOR2I coupledStart = m_origin;
|
||||||
VECTOR2I coupledEnd = m_end;
|
VECTOR2I coupledEnd = m_end;
|
||||||
|
|
|
@ -130,18 +130,6 @@ public:
|
||||||
void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) override;
|
void ClearCacheForItems( std::vector<const PNS::ITEM*>& aItems ) override;
|
||||||
void ClearCaches() override;
|
void ClearCaches() override;
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Checks for netnamed differential pairs.
|
|
||||||
* This accepts nets named suffixed by 'P', 'N', '+', '-', as well as additional
|
|
||||||
* numbers and underscores following the suffix. So NET_P_123 is a valid positive net
|
|
||||||
* name matched to NET_N_123.
|
|
||||||
* @param aNetName Input net name to check for DP naming
|
|
||||||
* @param aComplementNet Generated net name for the pair
|
|
||||||
* @return -1 if found the negative pair, +1 if found the positive pair, 0 otherwise
|
|
||||||
*/
|
|
||||||
int matchDpSuffix( const wxString& aNetName, wxString& aComplementNet );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PNS::ROUTER_IFACE* m_routerIface;
|
PNS::ROUTER_IFACE* m_routerIface;
|
||||||
BOARD* m_board;
|
BOARD* m_board;
|
||||||
|
@ -341,6 +329,7 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
|
||||||
case PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP: hostType = DIFF_PAIR_GAP_CONSTRAINT; break;
|
case PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP: hostType = DIFF_PAIR_GAP_CONSTRAINT; break;
|
||||||
case PNS::CONSTRAINT_TYPE::CT_LENGTH: hostType = LENGTH_CONSTRAINT; break;
|
case PNS::CONSTRAINT_TYPE::CT_LENGTH: hostType = LENGTH_CONSTRAINT; break;
|
||||||
case PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_SKEW: hostType = SKEW_CONSTRAINT; break;
|
case PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_SKEW: hostType = SKEW_CONSTRAINT; break;
|
||||||
|
case PNS::CONSTRAINT_TYPE::CT_MAX_UNCOUPLED: hostType = MAX_UNCOUPLED_CONSTRAINT; break;
|
||||||
case PNS::CONSTRAINT_TYPE::CT_VIA_DIAMETER: hostType = VIA_DIAMETER_CONSTRAINT; break;
|
case PNS::CONSTRAINT_TYPE::CT_VIA_DIAMETER: hostType = VIA_DIAMETER_CONSTRAINT; break;
|
||||||
case PNS::CONSTRAINT_TYPE::CT_VIA_HOLE: hostType = HOLE_SIZE_CONSTRAINT; break;
|
case PNS::CONSTRAINT_TYPE::CT_VIA_HOLE: hostType = HOLE_SIZE_CONSTRAINT; break;
|
||||||
case PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE: hostType = HOLE_CLEARANCE_CONSTRAINT; break;
|
case PNS::CONSTRAINT_TYPE::CT_HOLE_CLEARANCE: hostType = HOLE_CLEARANCE_CONSTRAINT; break;
|
||||||
|
@ -448,6 +437,7 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType,
|
||||||
case PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE:
|
case PNS::CONSTRAINT_TYPE::CT_HOLE_TO_HOLE:
|
||||||
case PNS::CONSTRAINT_TYPE::CT_LENGTH:
|
case PNS::CONSTRAINT_TYPE::CT_LENGTH:
|
||||||
case PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_SKEW:
|
case PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_SKEW:
|
||||||
|
case PNS::CONSTRAINT_TYPE::CT_MAX_UNCOUPLED:
|
||||||
aConstraint->m_Value = hostConstraint.GetValue();
|
aConstraint->m_Value = hostConstraint.GetValue();
|
||||||
aConstraint->m_RuleName = hostConstraint.GetName();
|
aConstraint->m_RuleName = hostConstraint.GetName();
|
||||||
aConstraint->m_Type = aType;
|
aConstraint->m_Type = aType;
|
||||||
|
@ -807,68 +797,9 @@ int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) con
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PNS_PCBNEW_RULE_RESOLVER::matchDpSuffix( const wxString& aNetName, wxString& aComplementNet )
|
|
||||||
{
|
|
||||||
int rv = 0;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
for( auto it = aNetName.rbegin(); it != aNetName.rend() && rv == 0; ++it, ++count )
|
|
||||||
{
|
|
||||||
int ch = *it;
|
|
||||||
|
|
||||||
if( ( ch >= '0' && ch <= '9' ) || ch == '_' )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if( ch == '+' )
|
|
||||||
{
|
|
||||||
aComplementNet = wxT( "-" );
|
|
||||||
rv = 1;
|
|
||||||
}
|
|
||||||
else if( ch == '-' )
|
|
||||||
{
|
|
||||||
aComplementNet = wxT( "+" );
|
|
||||||
rv = -1;
|
|
||||||
}
|
|
||||||
else if( ch == 'N' )
|
|
||||||
{
|
|
||||||
aComplementNet = wxT( "P" );
|
|
||||||
rv = -1;
|
|
||||||
}
|
|
||||||
else if ( ch == 'P' )
|
|
||||||
{
|
|
||||||
aComplementNet = wxT( "N" );
|
|
||||||
rv = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rv != 0 && count >= 1 )
|
|
||||||
{
|
|
||||||
aComplementNet = aNetName.Left( aNetName.length() - count )
|
|
||||||
+ aComplementNet
|
|
||||||
+ aNetName.Right( count - 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PNS::NET_HANDLE PNS_PCBNEW_RULE_RESOLVER::DpCoupledNet( PNS::NET_HANDLE aNet )
|
PNS::NET_HANDLE PNS_PCBNEW_RULE_RESOLVER::DpCoupledNet( PNS::NET_HANDLE aNet )
|
||||||
{
|
{
|
||||||
if( NETINFO_ITEM* net = static_cast<NETINFO_ITEM*>( aNet ) )
|
return m_board->DpCoupledNet( static_cast<NETINFO_ITEM*>( aNet ) );
|
||||||
{
|
|
||||||
wxString refName = net->GetNetname();
|
|
||||||
wxString coupledNetName;
|
|
||||||
|
|
||||||
if( matchDpSuffix( refName, coupledNetName ) )
|
|
||||||
return m_board->FindNet( coupledNetName );
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -893,7 +824,7 @@ int PNS_PCBNEW_RULE_RESOLVER::DpNetPolarity( PNS::NET_HANDLE aNet )
|
||||||
|
|
||||||
wxString dummy1;
|
wxString dummy1;
|
||||||
|
|
||||||
return matchDpSuffix( refName, dummy1 );
|
return m_board->MatchDpSuffix( refName, dummy1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -906,7 +837,7 @@ bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( const PNS::ITEM* aItem, PNS::NET_HANDL
|
||||||
wxString netNameP = static_cast<NETINFO_ITEM*>( aItem->Net() )->GetNetname();
|
wxString netNameP = static_cast<NETINFO_ITEM*>( aItem->Net() )->GetNetname();
|
||||||
wxString netNameN, netNameCoupled;
|
wxString netNameN, netNameCoupled;
|
||||||
|
|
||||||
int r = matchDpSuffix( netNameP, netNameCoupled );
|
int r = m_board->MatchDpSuffix( netNameP, netNameCoupled );
|
||||||
|
|
||||||
if( r == 0 )
|
if( r == 0 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,7 +59,8 @@ enum class CONSTRAINT_TYPE
|
||||||
CT_HOLE_CLEARANCE = 7,
|
CT_HOLE_CLEARANCE = 7,
|
||||||
CT_EDGE_CLEARANCE = 8,
|
CT_EDGE_CLEARANCE = 8,
|
||||||
CT_HOLE_TO_HOLE = 9,
|
CT_HOLE_TO_HOLE = 9,
|
||||||
CT_DIFF_PAIR_SKEW = 10
|
CT_DIFF_PAIR_SKEW = 10,
|
||||||
|
CT_MAX_UNCOUPLED = 11
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2536,6 +2536,7 @@ void ROUTER_TOOL::UpdateMessagePanel()
|
||||||
{
|
{
|
||||||
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
|
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
|
||||||
PNS::RULE_RESOLVER* resolver = m_iface->GetRuleResolver();
|
PNS::RULE_RESOLVER* resolver = m_iface->GetRuleResolver();
|
||||||
|
PNS::CONSTRAINT constraint;
|
||||||
std::vector<PNS::NET_HANDLE> nets = m_router->GetCurrentNets();
|
std::vector<PNS::NET_HANDLE> nets = m_router->GetCurrentNets();
|
||||||
wxString description;
|
wxString description;
|
||||||
wxString secondary;
|
wxString secondary;
|
||||||
|
@ -2620,6 +2621,18 @@ void ROUTER_TOOL::UpdateMessagePanel()
|
||||||
FORMAT_VALUE( sizes.DiffPairGap() ) ),
|
FORMAT_VALUE( sizes.DiffPairGap() ) ),
|
||||||
wxString::Format( _( "(from %s)" ),
|
wxString::Format( _( "(from %s)" ),
|
||||||
sizes.GetDiffPairGapSource() ) );
|
sizes.GetDiffPairGapSource() ) );
|
||||||
|
|
||||||
|
const PNS::ITEM_SET& traces = m_router->Placer()->Traces();
|
||||||
|
wxASSERT( traces.Count() == 2 );
|
||||||
|
|
||||||
|
if( resolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_MAX_UNCOUPLED, traces[0],
|
||||||
|
traces[1], m_router->GetCurrentLayer(), &constraint ) )
|
||||||
|
{
|
||||||
|
items.emplace_back( wxString::Format( _( "DP Max Uncoupled-length: %s" ),
|
||||||
|
FORMAT_VALUE( constraint.m_Value.Max() ) ),
|
||||||
|
wxString::Format( _( "(from %s)" ),
|
||||||
|
constraint.m_RuleName ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -315,7 +315,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
|
||||||
if( compileError )
|
if( compileError )
|
||||||
reportCompileError( r );
|
reportCompileError( r );
|
||||||
|
|
||||||
constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, a, b, layer, r );
|
constraint = drcEngine.EvalRules( MAX_UNCOUPLED_CONSTRAINT, a, b, layer, r );
|
||||||
|
|
||||||
r->Report( "" );
|
r->Report( "" );
|
||||||
r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
|
r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
|
||||||
|
@ -908,15 +908,14 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||||
reportHeader( _( "Diff-pair max uncoupled length resolution for:" ), ac, bc,
|
reportHeader( _( "Diff-pair max uncoupled length resolution for:" ), ac, bc,
|
||||||
active, r );
|
active, r );
|
||||||
|
|
||||||
if( !drcEngine.HasRulesForConstraintType( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT ) )
|
if( !drcEngine.HasRulesForConstraintType( MAX_UNCOUPLED_CONSTRAINT ) )
|
||||||
{
|
{
|
||||||
r->Report( "" );
|
r->Report( "" );
|
||||||
r->Report( _( "No 'diff_pair_uncoupled' constraints defined." ) );
|
r->Report( _( "No 'diff_pair_uncoupled' constraints defined." ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, ac, bc,
|
constraint = drcEngine.EvalRules( MAX_UNCOUPLED_CONSTRAINT, ac, bc, active, r );
|
||||||
active, r );
|
|
||||||
|
|
||||||
r->Report( "" );
|
r->Report( "" );
|
||||||
r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
|
r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ),
|
||||||
|
|
|
@ -1432,6 +1432,53 @@ int PCB_CONTROL::UpdateMessagePanel( const TOOL_EVENT& aEvent )
|
||||||
EDA_ITEM* item = selection.Front();
|
EDA_ITEM* item = selection.Front();
|
||||||
|
|
||||||
item->GetMsgPanelInfo( m_frame, msgItems );
|
item->GetMsgPanelInfo( m_frame, msgItems );
|
||||||
|
|
||||||
|
PCB_TRACK* track = dynamic_cast<PCB_TRACK*>( item );
|
||||||
|
NETINFO_ITEM* net = track ? track->GetNet() : nullptr;
|
||||||
|
NETINFO_ITEM* coupledNet = net ? m_frame->GetBoard()->DpCoupledNet( net ) : nullptr;
|
||||||
|
|
||||||
|
if( coupledNet )
|
||||||
|
{
|
||||||
|
SEG trackSeg( track->GetStart(), track->GetEnd() );
|
||||||
|
PCB_TRACK* coupledItem = nullptr;
|
||||||
|
SEG::ecoord closestDist_sq;
|
||||||
|
|
||||||
|
for( PCB_TRACK* candidate : m_frame->GetBoard()->Tracks() )
|
||||||
|
{
|
||||||
|
if( candidate->GetNet() != coupledNet )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SEG::ecoord dist_sq = trackSeg.SquaredDistance( SEG( candidate->GetStart(),
|
||||||
|
candidate->GetEnd() ) );
|
||||||
|
|
||||||
|
if( !coupledItem || dist_sq < closestDist_sq )
|
||||||
|
{
|
||||||
|
coupledItem = candidate;
|
||||||
|
closestDist_sq = dist_sq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint = drcEngine->EvalRules( DIFF_PAIR_GAP_CONSTRAINT, track, coupledItem,
|
||||||
|
track->GetLayer() );
|
||||||
|
|
||||||
|
wxString msg = m_frame->MessageTextFromMinOptMax( constraint.Value() );
|
||||||
|
|
||||||
|
if( !msg.IsEmpty() )
|
||||||
|
{
|
||||||
|
msgItems.emplace_back( wxString::Format( _( "DP Gap Constraints: %s" ), msg ),
|
||||||
|
wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint = drcEngine->EvalRules( MAX_UNCOUPLED_CONSTRAINT, track,
|
||||||
|
coupledItem, track->GetLayer() );
|
||||||
|
|
||||||
|
if( constraint.Value().HasMax() )
|
||||||
|
{
|
||||||
|
msg = m_frame->MessageTextFromValue( constraint.Value().Max() );
|
||||||
|
msgItems.emplace_back( wxString::Format( _( "DP Max Uncoupled-length: %s" ), msg ),
|
||||||
|
wxString::Format( _( "(from %s)" ), constraint.GetName() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( pcbFrame && selection.GetSize() == 2 )
|
else if( pcbFrame && selection.GetSize() == 2 )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue