KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_net_chain_total_length_sexpr.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <boost/test/unit_test.hpp>
22#include <board.h>
23#include <pcb_track.h>
24#include <netinfo.h>
25#include <pad.h>
26#include <footprint.h>
29
30static const long long MM = 1000000LL; // internal units
31
32static const char* BOARD_FILE = "net_chains/net_chain_total_length.kicad_pcb";
33
34BOOST_AUTO_TEST_SUITE( SignalTotalLengthSexpr )
35
36BOOST_AUTO_TEST_CASE( SignalAggregateMatchesPadSpacing )
37{
38 PCB_IO_KICAD_SEXPR plugin;
39 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
40 plugin.LoadBoard( KI_TEST::GetPcbnewTestDataDir() + BOARD_FILE, board.get() );
41 board->BuildConnectivity();
42
43 // Assign signal name
44 for( NETINFO_ITEM* net : board->GetNetInfo() )
45 if( net->GetNetCode() > 0 ) net->SetNetChain( wxS("Signal1") );
46
47 // Map net -> two pads (terminal pads) using pad net codes
48 std::map<int, std::vector<PAD*>> netPads;
49 for( FOOTPRINT* fp : board->Footprints() )
50 for( PAD* pad : fp->Pads() )
51 if( pad->GetNetCode() > 0 ) netPads[ pad->GetNetCode() ].push_back( pad );
52
53 for( auto& [code, pads] : netPads )
54 {
55 if( pads.size() >= 2 )
56 {
57 NETINFO_ITEM* net = board->FindNet( code );
58 net->SetTerminalPad( 0, pads[0] );
59 net->SetTerminalPad( 1, pads[1] );
60 }
61 }
62
63 NETINFO_ITEM* n1 = board->FindNet( wxS( "Net-(R1-Pad1)" ) );
64 BOOST_REQUIRE( n1 );
65
66 PNS_KICAD_IFACE_BASE ifaceBase; ifaceBase.SetBoard( board.get() );
67 long long extraLen = 0, extraDelay = 0;
68 bool ok = ifaceBase.GetSignalAggregate( n1, n1, extraLen, extraDelay );
69 BOOST_CHECK( ok );
70
71 // Compute actual routed length (with wiggles) and linear span for net1
72 long long net1TrackLen = 0;
73 bool havePoint = false; long long minX = 0, maxX = 0;
74 for( BOARD_ITEM* bi : board->Tracks() )
75 if( auto tr = dynamic_cast<PCB_TRACK*>( bi ) )
76 if( tr->GetNetCode() == n1->GetNetCode() )
77 {
78 net1TrackLen += ( tr->GetStart() - tr->GetEnd() ).EuclideanNorm();
79 long long sx = tr->GetStart().x; long long ex = tr->GetEnd().x;
80 if( !havePoint ) { minX = std::min( sx, ex ); maxX = std::max( sx, ex ); havePoint = true; }
81 else { minX = std::min( minX, std::min( sx, ex ) ); maxX = std::max( maxX, std::max( sx, ex ) ); }
82 }
83 long long net1Span = havePoint ? ( maxX - minX ) : 0;
84 BOOST_CHECK( net1Span > 0 );
85 BOOST_CHECK( net1TrackLen >= net1Span ); // jog increases physical path
86
87 // Chain layout: TP2(0,0) — net1 — R1 — net2 — R2 — net3 — R3 — net4 — TP1(30,0)
88 //
89 // Copper per net (tracks + jog segments):
90 // net1: 8.000 + 0.283 = 8.283 mm
91 // net2: 5.705 + 0.014 = 5.719 mm
92 // net3: 3.495 + 0.014 = 3.509 mm
93 // net4: 7.850 + 0.354 = 8.204 mm
94 // Total copper: 25.715 mm
95 //
96 // Bridging through resistors (pad-to-pad, not copper):
97 // R1: 1.65 mm, R2: 1.65 mm, R3: 1.65 mm = 4.95 mm
98 //
99 // Full chain: 25.715 + 4.95 = 30.665 mm
100 //
101 // GetSignalAggregate returns copper only (no bridging).
102 // extraLen = net2 + net3 + net4 copper = ~17.432 mm
103 long long totalCopper = net1TrackLen + extraLen;
104 long long expectedCopper = 25 * MM;
105 long long padSpacing = 30 * MM;
106 BOOST_CHECK_MESSAGE( totalCopper >= expectedCopper,
107 "RoutedTotal=" << totalCopper << " expected>=" << expectedCopper
108 << " net1Track=" << net1TrackLen << " extra=" << extraLen );
109 BOOST_CHECK( totalCopper < padSpacing ); // copper alone is less than pad spacing
110
111 // Compute bridging: pad-to-pad distance through each 2-net series component
112 long long bridging = 0;
113 for( FOOTPRINT* fp : board->Footprints() )
114 {
115 std::map<int, PAD*> chainPads;
116 for( PAD* pad : fp->Pads() )
117 {
118 NETINFO_ITEM* pn = pad->GetNet();
119 if( pn && !pn->GetNetChain().IsEmpty() )
120 chainPads.emplace( pn->GetNetCode(), pad );
121 }
122 if( chainPads.size() == 2 )
123 {
124 auto it = chainPads.begin();
125 PAD* p1 = it->second; ++it; PAD* p2 = it->second;
126 bridging += ( p1->GetCenter() - p2->GetCenter() ).EuclideanNorm();
127 }
128 }
129 BOOST_CHECK( bridging > 0 );
130
131 // Full chain length (copper + bridging) must cover the pad spacing
132 long long fullChain = totalCopper + bridging;
133 long long tol = 1 * MM;
134 BOOST_CHECK_MESSAGE( fullChain >= padSpacing && fullChain < padSpacing + tol,
135 "FullChain=" << fullChain << " padSpacing=" << padSpacing
136 << " copper=" << totalCopper << " bridging=" << bridging );
137}
138
General utilities for PCB file IO for QA programs.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:83
Handle the data for a net.
Definition netinfo.h:46
const wxString & GetNetChain() const
Definition netinfo.h:112
int GetNetCode() const
Definition netinfo.h:94
void SetTerminalPad(int aIndex, PAD *aPad)
Definition netinfo.h:116
Definition pad.h:61
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition pad.h:324
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
void SetBoard(BOARD *aBoard)
bool GetSignalAggregate(PNS::NET_HANDLE aNetP, PNS::NET_HANDLE aNetN, long long &aExtraLength, long long &aExtraDelay) const override
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
static const char * BOARD_FILE
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
static const long long MM