router: initial support for V6 Design Rules (width/clearance/diff pair width/diff pair gap). Still a lot of work to do!

This commit is contained in:
Tomasz Wlostowski 2020-10-09 00:01:09 +02:00
parent 9bef95418e
commit 38cef95da9
7 changed files with 203 additions and 197 deletions

View File

@ -57,6 +57,7 @@
#include "pns_arc.h"
#include "pns_routing_settings.h"
#include "pns_sizes_settings.h"
#include "pns_item.h"
#include "pns_solid.h"
#include "pns_segment.h"
@ -80,10 +81,10 @@ public:
//virtual int Clearance( int aNetCode ) const override;
virtual int DpCoupledNet( int aNet ) override;
virtual int DpNetPolarity( int aNet ) override;
virtual bool DpNetPair( PNS::ITEM* aItem, int& aNetP, int& aNetN ) override;
virtual bool DpNetPair( const PNS::ITEM* aItem, int& aNetP, int& aNetN ) override;
virtual bool IsDiffPair( const PNS::ITEM* aA, const PNS::ITEM* aB ) override;
virtual bool QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA, const PNS::ITEM* aItemB, int aLayer, PNS::CONSTRAINT* aConstraint ) override;
virtual wxString NetName( int aNet ) override;
private:
@ -95,15 +96,10 @@ private:
};
int holeRadius( const PNS::ITEM* aItem ) const;
int localPadClearance( const PNS::ITEM* aItem ) const;
int matchDpSuffix( const wxString& aNetName, wxString& aComplementNet, wxString& aBaseDpName );
PNS::ROUTER_IFACE* m_routerIface;
BOARD* m_board;
std::vector<CLEARANCE_ENT> m_netClearanceCache;
std::unordered_map<const D_PAD*, int> m_localClearanceCache;
int m_defaultClearance;
};
@ -111,58 +107,6 @@ PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER_I
m_routerIface( aRouterIface ),
m_board( aBoard )
{
m_netClearanceCache.resize( m_board->GetNetCount() );
// Build clearance cache for net classes
for( unsigned int i = 0; i < m_board->GetNetCount(); i++ )
{
NETINFO_ITEM* ni = m_board->FindNet( i );
if( ni == NULL )
continue;
CLEARANCE_ENT ent;
ent.coupledNet = DpCoupledNet( i );
wxString netClassName = ni->GetClassName();
NETCLASSPTR nc = m_board->GetDesignSettings().GetNetClasses().Find( netClassName );
int clearance = nc->GetClearance();
ent.clearance = clearance;
ent.dpClearance = nc->GetDiffPairGap();
m_netClearanceCache[i] = ent;
wxLogTrace( "PNS", "Add net %u netclass %s clearance %d Diff Pair clearance %d",
i, netClassName.mb_str(), clearance, ent.dpClearance );
}
// Build clearance cache for pads
for( MODULE* mod : m_board->Modules() )
{
int moduleClearance = mod->GetLocalClearance();
for( D_PAD* pad : mod->Pads() )
{
int padClearance = pad->GetLocalClearance();
if( padClearance > 0 )
m_localClearanceCache[ pad ] = padClearance;
else if( moduleClearance > 0 )
m_localClearanceCache[ pad ] = moduleClearance;
}
}
auto defaultRule = m_board->GetDesignSettings().GetNetClasses().Find ("Default");
if( defaultRule )
{
m_defaultClearance = defaultRule->GetClearance();
}
else
{
m_defaultClearance = Millimeter2iu(0.254);
}
}
@ -230,21 +174,22 @@ bool PNS_PCBNEW_RULE_RESOLVER::CollideHoles( const PNS::ITEM* aA, const PNS::ITE
}
int PNS_PCBNEW_RULE_RESOLVER::localPadClearance( const PNS::ITEM* aItem ) const
bool PNS_PCBNEW_RULE_RESOLVER::IsDiffPair( const PNS::ITEM* aA, const PNS::ITEM* aB )
{
if( !aItem->Parent() || aItem->Parent()->Type() != PCB_PAD_T )
return 0;
int net_p, net_n;
const D_PAD* pad = static_cast<D_PAD*>( aItem->Parent() );
DpNetPair( aA, net_p, net_n );
auto i = m_localClearanceCache.find( pad );
if( aA->Net() == net_p && aB->Net() == net_n )
return true;
if( aB->Net() == net_p && aA->Net() == net_n )
return true;
if( i == m_localClearanceCache.end() )
return 0;
return i->second;
return false;
}
bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA, const PNS::ITEM* aItemB, int aLayer, PNS::CONSTRAINT* aConstraint )
{
std::shared_ptr<DRC_ENGINE> drcEngine = m_board->GetDesignSettings().m_DRCEngine;
@ -274,24 +219,188 @@ bool PNS_PCBNEW_RULE_RESOLVER::QueryConstraint( PNS::CONSTRAINT_TYPE aType, cons
return false; // should not happen
}
const BOARD_ITEM* parentA = aItemA ? aItemA->Parent() : nullptr;
const BOARD_ITEM* parentB = aItemB ? aItemB->Parent() : nullptr;
DRC_CONSTRAINT hostConstraint = drcEngine->EvalRulesForItems( hostRuleType,
aItemA->Parent(),
aItemB->Parent(),
parentA,
parentB,
(PCB_LAYER_ID) aLayer );
if( hostConstraint.IsNull() )
return false;
switch ( aType )
{
case PNS::CONSTRAINT_TYPE::CT_CLEARANCE:
case PNS::CONSTRAINT_TYPE::CT_WIDTH:
case PNS::CONSTRAINT_TYPE::CT_DIFF_PAIR_GAP:
aConstraint->m_Value = hostConstraint.GetValue();
aConstraint->m_RuleName = hostConstraint.GetParentRule()->m_Name;
aConstraint->m_Type = aType;
return true;
}
return false;
}
int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB )
{
PNS::CONSTRAINT constraint;
bool ok = QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, aA->Layer(), &constraint );
bool ok = false;
int rv;
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 );
rv = constraint.m_Value.Opt();
printf("QueryDPCL %d\n", rv);
}
if( !ok )
{
ok = QueryConstraint( PNS::CONSTRAINT_TYPE::CT_CLEARANCE, aA, aB, aA->Layer(), &constraint );
rv = constraint.m_Value.Min();
printf("QueryCL %d\n", rv);
}
assert( ok );
return constraint.m_Value.Min();
return rv;
}
int PNS_KICAD_IFACE_BASE::inheritTrackWidth( PNS::ITEM* aItem )
{
VECTOR2I p;
assert( aItem->Owner() != NULL );
switch( aItem->Kind() )
{
case PNS::ITEM::VIA_T:
p = static_cast<PNS::VIA*>( aItem )->Pos();
break;
case PNS::ITEM::SOLID_T:
p = static_cast<PNS::SOLID*>( aItem )->Pos();
break;
case PNS::ITEM::SEGMENT_T:
return static_cast<PNS::SEGMENT*>( aItem )->Width();
default:
return 0;
}
PNS::JOINT* jt = static_cast<PNS::NODE*>( aItem->Owner() )->FindJoint( p, aItem );
assert( jt != NULL );
int mval = INT_MAX;
PNS::ITEM_SET linkedSegs = jt->Links();
linkedSegs.ExcludeItem( aItem ).FilterKinds( PNS::ITEM::SEGMENT_T );
for( PNS::ITEM* item : linkedSegs.Items() )
{
int w = static_cast<PNS::SEGMENT*>( item )->Width();
mval = std::min( w, mval );
}
return ( mval == INT_MAX ? 0 : mval );
}
bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM* aStartItem, int aNet )
{
BOARD_DESIGN_SETTINGS &bds = m_board->GetDesignSettings();
int net = aNet;
if( aStartItem )
net = aStartItem->Net();
int trackWidth = 0;
if( bds.m_UseConnectedTrackWidth && aStartItem != nullptr )
{
trackWidth = inheritTrackWidth( aStartItem );
}
if( !trackWidth && bds.UseNetClassTrack() ) // netclass value
{
PNS::CONSTRAINT constraint;
bool ok = m_ruleResolver->QueryConstraint( PNS::CONSTRAINT_TYPE::CT_WIDTH, aStartItem,
nullptr, aStartItem->Layer(), &constraint );
if( ok )
{
trackWidth = constraint.m_Value.HasOpt() ? constraint.m_Value.Opt() : constraint.m_Value.Min();
}
}
if( !trackWidth )
{
trackWidth = bds.GetCurrentTrackWidth();
}
aSizes.SetTrackWidth( trackWidth );
int viaDiameter = 0;
int viaDrill = 0;
if( bds.UseNetClassVia() ) // netclass value
{
viaDiameter = 0; //netClass->GetViaDiameter();
viaDrill = 0; //netClass->GetViaDrill(); // fixme
}
else
{
viaDiameter = bds.GetCurrentViaSize();
viaDrill = bds.GetCurrentViaDrill();
}
aSizes.SetViaDiameter( viaDiameter );
aSizes.SetViaDrill( viaDrill );
int diffPairWidth = 0;
int diffPairGap = 0;
int diffPairViaGap = 0;
if( bds.UseNetClassDiffPair() )
{
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( okWidth )
diffPairWidth = widthConstraint.m_Value.OptThenMin();
if( okGap )
diffPairViaGap = diffPairGap = gapConstraint.m_Value.OptThenMin();
}
else if( bds.UseCustomDiffPairDimensions() )
{
diffPairWidth = bds.GetCustomDiffPairWidth();
diffPairGap = bds.GetCustomDiffPairGap();
diffPairViaGap = bds.GetCustomDiffPairViaGap();
}
//printf("DPWidth: %d gap %d\n", diffPairWidth, diffPairGap );
aSizes.SetDiffPairWidth( diffPairWidth );
aSizes.SetDiffPairGap( diffPairGap );
aSizes.SetDiffPairViaGap( diffPairViaGap );
aSizes.ClearLayerPairs();
return true;
}
@ -388,7 +497,7 @@ int PNS_PCBNEW_RULE_RESOLVER::DpNetPolarity( int aNet )
}
bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( PNS::ITEM* aItem, int& aNetP, int& aNetN )
bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( const PNS::ITEM* aItem, int& aNetP, int& aNetN )
{
if( !aItem || !aItem->Parent() || !aItem->Parent()->GetNet() )
return false;

View File

@ -36,6 +36,11 @@ class PCB_TOOL_BASE;
class MODULE;
class D_PAD;
namespace PNS
{
class SIZES_SETTINGS;
}
namespace KIGFX
{
class VIEW;
@ -60,6 +65,7 @@ public:
void AddItem( PNS::ITEM* aItem ) override;
void RemoveItem( PNS::ITEM* aItem ) override;
void Commit() override {}
bool ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM* aStartItem, int aNet ) override;
void UpdateNet( int aNetCode ) override {}
@ -89,6 +95,8 @@ protected:
bool syncTextItem( PNS::NODE* aWorld, EDA_TEXT* aText, PCB_LAYER_ID aLayer );
bool syncGraphicalItem( PNS::NODE* aWorld, PCB_SHAPE* aItem );
bool syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone );
int inheritTrackWidth( PNS::ITEM* aItem );
PNS::NODE* m_world;
BOARD* m_board;

View File

@ -60,7 +60,9 @@ enum class CONSTRAINT_TYPE
CT_CLEARANCE = 1,
CT_DIFF_PAIR_GAP = 2,
CT_LENGTH = 3,
CT_WIDTH = 4
CT_WIDTH = 4,
CT_VIA_DIAMETER = 5,
CT_VIA_HOLE = 6
};
struct CONSTRAINT
@ -85,7 +87,9 @@ public:
//virtual int Clearance( int aNetCode ) const = 0;
virtual int DpCoupledNet( int aNet ) = 0;
virtual int DpNetPolarity( int aNet ) = 0;
virtual bool DpNetPair( ITEM* aItem, int& aNetP, int& aNetN ) = 0;
virtual bool DpNetPair( const ITEM* aItem, int& aNetP, int& aNetN ) = 0;
virtual bool IsDiffPair( const ITEM* aA, const ITEM* aB ) = 0;
virtual bool QueryConstraint( CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA, const PNS::ITEM* aItemB, int aLayer, PNS::CONSTRAINT* aConstraint ) = 0;

View File

@ -104,6 +104,7 @@ enum DRAG_MODE
virtual void DisplayItem( const ITEM* aItem, int aColor = -1, int aClearance = -1, bool aEdit = false ) = 0;
virtual void HideItem( ITEM* aItem ) = 0;
virtual void Commit() = 0;
virtual bool ImportSizes( SIZES_SETTINGS& aSizes, ITEM* aStartItem, int aNet ) = 0;
// virtual void Abort () = 0;
virtual void EraseView() = 0;

View File

@ -29,123 +29,6 @@
namespace PNS {
int SIZES_SETTINGS::inheritTrackWidth( ITEM* aItem )
{
VECTOR2I p;
assert( aItem->Owner() != NULL );
switch( aItem->Kind() )
{
case ITEM::VIA_T:
p = static_cast<VIA*>( aItem )->Pos();
break;
case ITEM::SOLID_T:
p = static_cast<SOLID*>( aItem )->Pos();
break;
case ITEM::SEGMENT_T:
return static_cast<SEGMENT*>( aItem )->Width();
default:
return 0;
}
JOINT* jt = static_cast<NODE*>( aItem->Owner() )->FindJoint( p, aItem );
assert( jt != NULL );
int mval = INT_MAX;
ITEM_SET linkedSegs = jt->Links();
linkedSegs.ExcludeItem( aItem ).FilterKinds( ITEM::SEGMENT_T );
for( ITEM* item : linkedSegs.Items() )
{
int w = static_cast<SEGMENT*>( item )->Width();
mval = std::min( w, mval );
}
return ( mval == INT_MAX ? 0 : mval );
}
void SIZES_SETTINGS::Init( BOARD* aBoard, ITEM* aStartItem, int aNet )
{
BOARD_DESIGN_SETTINGS &bds = aBoard->GetDesignSettings();
NETCLASSPTR netClass;
int net = aNet;
if( aStartItem )
net = aStartItem->Net();
if( net >= 0 )
{
NETINFO_ITEM* ni = aBoard->FindNet( net );
if( ni )
{
wxString netClassName = ni->GetClassName();
netClass = bds.GetNetClasses().Find( netClassName );
}
}
if( !netClass )
netClass = bds.GetNetClasses().GetDefault();
m_trackWidth = 0;
if( bds.m_UseConnectedTrackWidth && aStartItem != NULL )
{
m_trackWidth = inheritTrackWidth( aStartItem );
}
if( !m_trackWidth && ( bds.UseNetClassTrack() && netClass != NULL ) ) // netclass value
{
m_trackWidth = netClass->GetTrackWidth();
}
if( !m_trackWidth )
{
m_trackWidth = bds.GetCurrentTrackWidth();
}
if( bds.UseNetClassVia() && netClass != NULL ) // netclass value
{
m_viaDiameter = netClass->GetViaDiameter();
m_viaDrill = netClass->GetViaDrill();
}
else
{
m_viaDiameter = bds.GetCurrentViaSize();
m_viaDrill = bds.GetCurrentViaDrill();
}
if( bds.UseNetClassDiffPair() && netClass != NULL )
{
m_diffPairWidth = netClass->GetDiffPairWidth();
m_diffPairGap = netClass->GetDiffPairGap();
m_diffPairViaGap = netClass->GetDiffPairViaGap();
}
else if( bds.UseCustomDiffPairDimensions() )
{
m_diffPairWidth = bds.GetCustomDiffPairWidth();
m_diffPairGap = bds.GetCustomDiffPairGap();
m_diffPairViaGap = bds.GetCustomDiffPairViaGap();
}
else
{
m_diffPairWidth = bds.m_DiffPairDimensionsList[ bds.GetDiffPairIndex() ].m_Width;
m_diffPairGap = bds.m_DiffPairDimensionsList[ bds.GetDiffPairIndex() ].m_Gap;
m_diffPairViaGap = bds.m_DiffPairDimensionsList[ bds.GetDiffPairIndex() ].m_ViaGap;
}
m_layerPairs.clear();
}
void SIZES_SETTINGS::ClearLayerPairs()
{
@ -163,6 +46,7 @@ void SIZES_SETTINGS::AddLayerPair( int aL1, int aL2 )
}
#if 0
void SIZES_SETTINGS::ImportCurrent( BOARD_DESIGN_SETTINGS& aSettings )
{
m_trackWidth = aSettings.GetCurrentTrackWidth();
@ -173,6 +57,7 @@ void SIZES_SETTINGS::ImportCurrent( BOARD_DESIGN_SETTINGS& aSettings )
m_diffPairGap = aSettings.GetCurrentDiffPairGap();
m_diffPairViaGap = aSettings.GetCurrentDiffPairViaGap();
}
#endif
int SIZES_SETTINGS::GetLayerTop() const

View File

@ -49,9 +49,6 @@ public:
~SIZES_SETTINGS() {};
void Init( BOARD* aBoard, ITEM* aStartItem = NULL, int aNet = -1 );
void ImportCurrent( BOARD_DESIGN_SETTINGS& aSettings );
void ClearLayerPairs();
void AddLayerPair( int aL1, int aL2 );

View File

@ -874,9 +874,10 @@ bool ROUTER_TOOL::prepareInteractive()
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
sizes.Init( board(), m_startItem );
m_iface->ImportSizes( sizes, m_startItem, -1 );
sizes.AddLayerPair( frame()->GetScreen()->m_Route_Layer_TOP,
frame()->GetScreen()->m_Route_Layer_BOTTOM );
m_router->UpdateSizes( sizes );
if( !m_router->StartRouting( m_startSnapPoint, m_startItem, routingLayer ) )
@ -1635,7 +1636,8 @@ int ROUTER_TOOL::CustomTrackWidthDialog( const TOOL_EVENT& aEvent )
int ROUTER_TOOL::onTrackViaSizeChanged( const TOOL_EVENT& aEvent )
{
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
sizes.ImportCurrent( board()->GetDesignSettings() );
m_iface->ImportSizes( sizes, nullptr, m_router->GetCurrentNets()[0] );
m_router->UpdateSizes( sizes );
// Changing the track width can affect the placement, so call the