KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_issue24134_bus_fork_at_entry.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, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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, you may find one here:
18 * https://www.gnu.org/licenses/gpl-3.0.en.html
19 * or you may search the http://www.gnu.org website for the version 3 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
33
35
36#include <junction_helpers.h>
37
38#include <connection_graph.h>
39#include <sch_bus_entry.h>
40#include <sch_junction.h>
41#include <sch_line.h>
42#include <sch_sheet.h>
43#include <sch_sheet_path.h>
44#include <sch_screen.h>
45#include <schematic.h>
47#include <project.h>
48
49using namespace JUNCTION_HELPERS;
50
51static constexpr int BE_SIZE = 25400;
52
53static SCH_LINE* make_bus( const VECTOR2I& aStart, const VECTOR2I& aEnd )
54{
55 SCH_LINE* const line = new SCH_LINE{ aStart, LAYER_BUS };
56 line->SetEndPoint( aEnd );
57 return line;
58}
59
60
65BOOST_AUTO_TEST_CASE( BusForkAtBusEntryIsJunction )
66{
67 /*
68 * || /--- forked bus
69 * || /
70 * ===========O ====== through bus (forks here)
71 * ||\
72 * || \ bus entry
73 */
74 EE_RTREE items;
75
76 // Through bus passing across the fork point (0, 0) as a midpoint
77 items.insert( make_bus( { -BE_SIZE, 0 }, { 0, 0 } ) );
78 items.insert( make_bus( { 0, 0 }, { BE_SIZE, 0 } ) );
79
80 // A third bus forking upward from the same point
81 items.insert( make_bus( { 0, 0 }, { 0, -BE_SIZE } ) );
82
83 // Wire-to-bus entry rooted at the same point
84 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
85
86 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
87
88 BOOST_CHECK( info.isJunction );
89 BOOST_CHECK( info.hasBusEntry );
90
91 // The genuine three-way bus fork must be recognized despite the entry footprint.
92 BOOST_CHECK_MESSAGE( info.hasBusEntryToMultipleBuses,
93 "A bus forking at a bus-entry root must be a real bus junction "
94 "(issue #24134)" );
95}
96
97
102BOOST_AUTO_TEST_CASE( StraightBusWithEntryIsNotMultiBusFork )
103{
104 EE_RTREE items;
105
106 // Straight bus through the point, plus a single wire and a bus entry (no third bus)
107 items.insert( make_bus( { -BE_SIZE, 0 }, { 0, 0 } ) );
108 items.insert( make_bus( { 0, 0 }, { BE_SIZE, 0 } ) );
109 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
110
111 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
112
113 BOOST_CHECK( info.hasBusEntry );
114 BOOST_CHECK( !info.hasBusEntryToMultipleBuses );
115}
116
117
122BOOST_AUTO_TEST_CASE( CrossingBusesAtEntryRootAreNotAFork )
123{
124 /*
125 * ||
126 * =========++======== two buses pass straight through, crossing
127 * ||\
128 * || \ bus entry
129 */
130 EE_RTREE items;
131
132 // Two buses passing straight through the point (each as a midpoint, neither terminating)
133 items.insert( make_bus( { -BE_SIZE, 0 }, { BE_SIZE, 0 } ) );
134 items.insert( make_bus( { 0, -BE_SIZE }, { 0, BE_SIZE } ) );
135
136 items.insert( new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false ) );
137
138 const POINT_INFO info = AnalyzePoint( items, { 0, 0 }, false );
139
140 BOOST_CHECK( info.hasBusEntry );
141
142 // No bus terminates here, so this is a crossing, not a fork.
143 BOOST_CHECK_MESSAGE( !info.hasBusEntryToMultipleBuses,
144 "Two buses crossing at a bus-entry root must not be treated as a fork "
145 "(issue #24134)" );
146}
147
148
153BOOST_AUTO_TEST_CASE( BusForkAtEntryConnectsToSameBus )
154{
155 SETTINGS_MANAGER manager;
156 manager.LoadProject( "" );
157
158 SCHEMATIC schematic( &manager.Prj() );
159 schematic.Reset();
160 SCH_SHEET* defaultSheet = schematic.GetTopLevelSheet( 0 );
161
162 SCH_SCREEN* screen = new SCH_SCREEN( nullptr );
163 SCH_SHEET* sheet = new SCH_SHEET( nullptr, VECTOR2I( 0, 0 ), VECTOR2I( 200000, 200000 ) );
164 sheet->SetScreen( screen );
165 schematic.AddTopLevelSheet( sheet );
166 schematic.RemoveTopLevelSheet( defaultSheet );
167 delete defaultSheet;
168
169 SCH_SHEET_PATH sheetPath;
170 sheetPath.push_back( sheet );
171
172 // Through bus, not split at the fork point (0, 0)
173 SCH_LINE* throughBus = make_bus( { -BE_SIZE, 0 }, { BE_SIZE, 0 } );
174
175 // Forked bus branching from the fork point
176 SCH_LINE* forkBus = make_bus( { 0, 0 }, { 0, -BE_SIZE } );
177
178 // Wire-to-bus entry sitting on the bus at the fork point
179 SCH_BUS_WIRE_ENTRY* busEntry = new SCH_BUS_WIRE_ENTRY( { 0, 0 }, false );
180
181 screen->Append( throughBus, false );
182 screen->Append( forkBus, false );
183 screen->Append( busEntry, false );
184
185 // The editor would auto-place this bus junction; it must be permitted at the fork.
186 BOOST_REQUIRE_MESSAGE( screen->IsExplicitJunctionNeeded( VECTOR2I( 0, 0 ) ),
187 "A bus junction must be allowed adjacent to the bus entry "
188 "(issue #24134)" );
189
190 SCH_JUNCTION* junction = new SCH_JUNCTION( VECTOR2I( 0, 0 ) );
191 screen->Append( junction, false );
192
193 CONNECTION_GRAPH graph;
194 graph.SetSchematic( &schematic );
195
197 graph.Recalculate( sheets, true );
198
199 CONNECTION_SUBGRAPH* sgThrough = graph.GetSubgraphForItem( throughBus );
200 CONNECTION_SUBGRAPH* sgFork = graph.GetSubgraphForItem( forkBus );
201
202 BOOST_REQUIRE( sgThrough );
203 BOOST_REQUIRE( sgFork );
204
205 BOOST_CHECK_MESSAGE( sgThrough == sgFork,
206 "Forked bus must belong to the same bus subgraph as the through bus "
207 "rather than a NO_NET net (issue #24134)" );
208}
Calculate the connectivity of a schematic and generate netlists.
void SetSchematic(SCHEMATIC *aSchematic)
void Recalculate(const SCH_SHEET_LIST &aSheetList, bool aUnconditional=false, std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Update the connection graph for the given list of sheets.
CONNECTION_SUBGRAPH * GetSubgraphForItem(SCH_ITEM *aItem) const
A subgraph is a set of items that are electrically connected on a single sheet.
Implement an R-tree for fast spatial and type indexing of schematic items.
Definition sch_rtree.h:37
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
Definition sch_rtree.h:70
Holds all the data relating to one schematic.
Definition schematic.h:148
void Reset()
Initialize this schematic to a blank one, unloading anything existing.
void AddTopLevelSheet(SCH_SHEET *aSheet)
Add a new top-level sheet to the schematic.
SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const
SCH_SHEET * GetTopLevelSheet(int aIndex=0) const
bool RemoveTopLevelSheet(SCH_SHEET *aSheet)
Remove a top-level sheet from the schematic.
Class for a wire to bus entry.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:146
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
bool IsExplicitJunctionNeeded(const VECTOR2I &aPosition) const
Indicate that a junction dot is necessary at the given location, and does not yet exist.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
@ LAYER_BUS
Definition layer_ids.h:475
POINT_INFO AnalyzePoint(const EE_RTREE &aItem, const VECTOR2I &aPosition, bool aBreakCrossings)
Check a tree of items for a confluence at a given point and work out what kind of junction it is,...
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
A selection of information about a point in the schematic that might be eligible for turning into a j...
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_CASE(BusForkAtBusEntryIsJunction)
Junction analysis: a bus fork at a wire-to-bus entry root is a junction that the editor is allowed (a...
static constexpr int BE_SIZE
static SCH_LINE * make_bus(const VECTOR2I &aStart, const VECTOR2I &aEnd)
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683