@tscircuit/matchpack 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # matchpack
2
+
3
+ The goal of this module is to find the best schematic layout for a set of `SchematicChip`s and `SchematicGroups` containing
4
+ `SchematicPins` connected to each other with `SchematicTraces`
5
+
6
+ To do this, we use a series of solvers that are run in a pipeline. Each solver is responsible for a specific piece of
7
+ input preprocessing or calculation.
8
+
9
+ This is roughly the hierarchy of solvers:
10
+
11
+ ```
12
+ LayoutPipelineSolver: Runs pipeline
13
+ ↳ ChipPartitionsSolver: Creates partitions (small subset groups) surrounding complex chips
14
+ ↳ SingleChipPartitionSolver: Creates a single partition for a single chip
15
+ ↳ PinRangeMatchSolver: Finds pin ranges on each chip in the partition, constructs a subset group with just that pin range, then matches a laid out design from the corpus
16
+ ↳ PinRangeLayoutSolver: Applies the matched layout to the pin ranges, moving passives that are connected to each pin range
17
+ ↳ PinRangeOverlapSolver: Finds overlaps between laid out boxes from each pin range and fixes them
18
+ ↳ PartitionPackingSolver: Packs the laid out chip partitions into a single layout
19
+ ```
20
+
21
+ ## Implementation Notes
22
+
23
+ - There is the concept of a "weak" and "strong" connection between pins. A "strong" connection is one where a pin is directly assigned to another pin. A "weak" connection is generally a pin assigned to a net like "GND" or "VCC". Strong connections are important for layout but weak connections often determine orientation of passives (e.g. a capacitor is "facing up" to VCC but "facing down" to GND)
24
+ - Often there are pre-laid-out designs that are passed in. This is represented by a `SchematicGroup`. We don't lay out anything inside of these groups but the inner pins are still used to compute a good packing
@@ -0,0 +1,315 @@
1
+ import { GraphicsObject } from 'graphics-debug';
2
+ import { Point, Bounds } from '@tscircuit/math-utils';
3
+ import { PhasedPackSolver } from 'calculate-packing';
4
+
5
+ declare class BaseSolver {
6
+ MAX_ITERATIONS: number;
7
+ solved: boolean;
8
+ failed: boolean;
9
+ iterations: number;
10
+ progress: number;
11
+ error: string | null;
12
+ activeSubSolver?: BaseSolver | null;
13
+ failedSubSolvers?: BaseSolver[];
14
+ timeToSolve?: number;
15
+ stats: Record<string, any>;
16
+ /** DO NOT OVERRIDE! Override _step() instead */
17
+ step(): void;
18
+ _step(): void;
19
+ getConstructorParams(): void;
20
+ solve(): void;
21
+ visualize(): GraphicsObject;
22
+ /**
23
+ * Called when the solver is about to fail, but we want to see if we have an
24
+ * "acceptable" or "passable" solution. Mostly used for optimizers that
25
+ * have an aggressive early stopping criterion.
26
+ */
27
+ tryFinalAcceptance(): void;
28
+ /**
29
+ * A lightweight version of the visualize method that can be used to stream
30
+ * progress
31
+ */
32
+ preview(): GraphicsObject;
33
+ }
34
+
35
+ type Side = "x-" | "x+" | "y-" | "y+";
36
+
37
+ type PinId = string;
38
+ type ChipId = string;
39
+ type GroupId = string;
40
+ type NetId = string;
41
+ type ChipPin = {
42
+ pinId: PinId;
43
+ offset: Point;
44
+ side: Side;
45
+ };
46
+ type Chip = {
47
+ chipId: ChipId;
48
+ pins: PinId[];
49
+ size: Point;
50
+ };
51
+ type Group = {
52
+ groupId: GroupId;
53
+ pins: PinId[];
54
+ /** The shape of the group is defined by a set of bounding boxes */
55
+ shape: Bounds[];
56
+ };
57
+ type GroupPin = {
58
+ pinId: PinId;
59
+ offset: Point;
60
+ };
61
+ type Net = {
62
+ netId: NetId;
63
+ };
64
+ type InputProblem = {
65
+ chipMap: Record<ChipId, Chip>;
66
+ chipPinMap: Record<PinId, ChipPin>;
67
+ groupMap: Record<GroupId, Group>;
68
+ groupPinMap: Record<PinId, GroupPin>;
69
+ netMap: Record<NetId, Net>;
70
+ /** This is a two-way map */
71
+ pinStrongConnMap: Record<`${PinId}-${PinId}`, boolean>;
72
+ netConnMap: Record<`${PinId}-${NetId}`, boolean>;
73
+ };
74
+
75
+ /**
76
+ * Creates partitions (small subset groups) surrounding complex chips.
77
+ * Divides the layout problem into manageable sections for more efficient processing.
78
+ */
79
+
80
+ declare class ChipPartitionsSolver extends BaseSolver {
81
+ inputProblem: InputProblem;
82
+ partitions: InputProblem[];
83
+ constructor(inputProblem: InputProblem);
84
+ _step(): void;
85
+ /**
86
+ * Creates partitions by finding connected components through strong pin connections
87
+ */
88
+ private createPartitions;
89
+ /**
90
+ * Finds the owner (chip or group) of a given pin
91
+ */
92
+ private findPinOwner;
93
+ /**
94
+ * Depth-first search to find connected components
95
+ */
96
+ private dfs;
97
+ /**
98
+ * Creates a new InputProblem containing only the components in the given partition
99
+ */
100
+ private createInputProblemFromPartition;
101
+ visualize(): GraphicsObject;
102
+ }
103
+
104
+ type Placement = Point & {
105
+ ccwRotationDegrees: number;
106
+ };
107
+ type OutputLayout = {
108
+ chipPlacements: Record<ChipId, Placement>;
109
+ groupPlacements: Record<GroupId, Placement>;
110
+ };
111
+
112
+ /**
113
+ * Packs the laid out chip partitions into a single layout.
114
+ * Combines all the individually processed partitions into the final schematic layout.
115
+ */
116
+
117
+ type LaidOutPartition = InputProblem;
118
+ interface PartitionPackingSolverInput {
119
+ resolvedLayout: OutputLayout;
120
+ laidOutPartitions: LaidOutPartition[];
121
+ }
122
+ declare class PartitionPackingSolver extends BaseSolver {
123
+ resolvedLayout: OutputLayout;
124
+ laidOutPartitions: LaidOutPartition[];
125
+ finalLayout: OutputLayout | null;
126
+ phasedPackSolver: PhasedPackSolver | null;
127
+ constructor(input: PartitionPackingSolverInput);
128
+ _step(): void;
129
+ private organizeComponentsByPartition;
130
+ private createPackInput;
131
+ private applyPackingResult;
132
+ visualize(): GraphicsObject;
133
+ getConstructorParams(): PartitionPackingSolverInput;
134
+ }
135
+
136
+ /**
137
+ * Sub-solver for processing pin ranges within a single partition
138
+ */
139
+
140
+ type PinRange = {
141
+ pinIds: PinId[];
142
+ side: Side;
143
+ chipId?: ChipId;
144
+ groupId?: GroupId;
145
+ connectedPins?: PinId[];
146
+ connectedChips?: ChipId[];
147
+ };
148
+ declare class PartitionPinRangeMatchSolver extends BaseSolver {
149
+ inputProblem: InputProblem;
150
+ pinRanges: PinRange[];
151
+ constructor(inputProblem: InputProblem);
152
+ _step(): void;
153
+ private createPinRanges;
154
+ private createPinRangesForChip;
155
+ private createPinRangesForGroup;
156
+ private createPinRangesForSide;
157
+ private sortPinsBySide;
158
+ private calculateDistance;
159
+ private findConnectedPassives;
160
+ visualize(): GraphicsObject;
161
+ getConstructorParams(): {
162
+ inputProblem: InputProblem;
163
+ };
164
+ }
165
+
166
+ /**
167
+ * Solves the layout for a single pin range and its connected passive components.
168
+ * This solver takes a pin range and applies layout patterns to position the
169
+ * connected components optimally around the pin range.
170
+ */
171
+
172
+ declare class SinglePinRangeLayoutSolver extends BaseSolver {
173
+ pinRange: PinRange;
174
+ inputProblem: InputProblem;
175
+ layoutApplied: boolean;
176
+ layout: OutputLayout | null;
177
+ debugPackInput: any;
178
+ constructor(pinRange: PinRange, inputProblem: InputProblem);
179
+ _step(): void;
180
+ /**
181
+ * Build a connectivity map that normalizes network IDs by finding connected components.
182
+ * All pins in the same connected component get the same network ID.
183
+ */
184
+ protected buildNetworkConnectivityMap(relevantPins: Set<string>): Map<string, string>;
185
+ protected createPinRangeLayout(): OutputLayout;
186
+ visualize(): GraphicsObject;
187
+ getConstructorParams(): {
188
+ pinRange: PinRange;
189
+ inputProblem: InputProblem;
190
+ };
191
+ }
192
+
193
+ /**
194
+ * Applies the matched layout to the pin ranges.
195
+ * Moves passives that are connected to each pin range according to the matched design.
196
+ */
197
+
198
+ declare class PinRangeLayoutSolver extends BaseSolver {
199
+ pinRanges: PinRange[];
200
+ inputProblems: InputProblem[];
201
+ currentRangeIndex: number;
202
+ activeSolver: SinglePinRangeLayoutSolver | null;
203
+ completedSolvers: SinglePinRangeLayoutSolver[];
204
+ constructor(pinRanges: PinRange[], inputProblems: InputProblem[]);
205
+ _step(): void;
206
+ private findInputProblemForRange;
207
+ visualize(): GraphicsObject;
208
+ getConstructorParams(): {
209
+ pinRanges: PinRange[];
210
+ inputProblems: InputProblem[];
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Finds pin ranges on each chip in the partition and matches layouts from the corpus.
216
+ * Creates subset groups with pin ranges and finds pre-laid-out designs that match.
217
+ */
218
+
219
+ declare class PinRangeMatchSolver extends BaseSolver {
220
+ partitions: InputProblem[];
221
+ currentPartitionIndex: number;
222
+ activeSubSolver: PartitionPinRangeMatchSolver | null;
223
+ partitionResults: PinRange[][];
224
+ constructor(partitions: InputProblem[]);
225
+ _step(): void;
226
+ getAllPinRanges(): PinRange[];
227
+ visualize(): GraphicsObject;
228
+ getConstructorParams(): {
229
+ partitions: InputProblem[];
230
+ };
231
+ }
232
+
233
+ /**
234
+ * Finds overlaps between laid out boxes from each pin range and fixes them.
235
+ * Resolves spatial conflicts between different pin range layouts.
236
+ */
237
+
238
+ declare class PinRangeOverlapSolver extends BaseSolver {
239
+ pinRangeLayoutSolver: PinRangeLayoutSolver | null;
240
+ inputProblems: InputProblem[];
241
+ resolvedLayout: OutputLayout | null;
242
+ constructor(pinRangeLayoutSolver: PinRangeLayoutSolver, inputProblems: InputProblem[]);
243
+ _step(): void;
244
+ private groupPlacementsByPartition;
245
+ private findPartitionIndexForSolver;
246
+ private resolvePartitionOverlaps;
247
+ private positionPartitionsHorizontally;
248
+ private findOverlaps;
249
+ private getComponentBounds;
250
+ private boundsOverlap;
251
+ private resolveOverlaps;
252
+ visualize(): GraphicsObject;
253
+ getConstructorParams(): {
254
+ pinRangeLayoutSolver: PinRangeLayoutSolver | null;
255
+ inputProblems: InputProblem[];
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Pipeline solver that runs a series of solvers to find the best schematic layout.
261
+ * Coordinates the entire layout process from chip partitioning through final packing.
262
+ */
263
+
264
+ type PipelineStep<T extends new (...args: any[]) => BaseSolver> = {
265
+ solverName: string;
266
+ solverClass: T;
267
+ getConstructorParams: (instance: LayoutPipelineSolver) => ConstructorParameters<T>;
268
+ onSolved?: (instance: LayoutPipelineSolver) => void;
269
+ };
270
+ declare class LayoutPipelineSolver extends BaseSolver {
271
+ chipPartitionsSolver?: ChipPartitionsSolver;
272
+ pinRangeMatchSolver?: PinRangeMatchSolver;
273
+ pinRangeLayoutSolver?: PinRangeLayoutSolver;
274
+ pinRangeOverlapSolver?: PinRangeOverlapSolver;
275
+ partitionPackingSolver?: PartitionPackingSolver;
276
+ startTimeOfPhase: Record<string, number>;
277
+ endTimeOfPhase: Record<string, number>;
278
+ timeSpentOnPhase: Record<string, number>;
279
+ firstIterationOfPhase: Record<string, number>;
280
+ inputProblem: InputProblem;
281
+ chipPartitions?: ChipPartitionsSolver["partitions"];
282
+ pinRanges?: ReturnType<PinRangeMatchSolver["getAllPinRanges"]>;
283
+ pipelineDef: (PipelineStep<typeof ChipPartitionsSolver> | PipelineStep<typeof PinRangeMatchSolver> | PipelineStep<typeof PinRangeLayoutSolver> | PipelineStep<typeof PinRangeOverlapSolver> | PipelineStep<typeof PartitionPackingSolver>)[];
284
+ constructor(inputProblem: InputProblem);
285
+ currentPipelineStepIndex: number;
286
+ _step(): void;
287
+ solveUntilPhase(phase: string): void;
288
+ getCurrentPhase(): string;
289
+ visualize(): GraphicsObject;
290
+ /**
291
+ * A lightweight version of the visualize method that can be used to stream
292
+ * progress
293
+ */
294
+ preview(): GraphicsObject;
295
+ /**
296
+ * Checks if any chips are overlapping in the given layout, considering rotation.
297
+ * Returns an array of overlapping chip pairs.
298
+ */
299
+ checkForOverlaps(layout: OutputLayout): Array<{
300
+ chip1: string;
301
+ chip2: string;
302
+ overlapArea: number;
303
+ }>;
304
+ /**
305
+ * Calculate the axis-aligned bounding box for a rotated chip
306
+ */
307
+ private getRotatedBounds;
308
+ /**
309
+ * Calculate the overlap area between two axis-aligned bounding boxes
310
+ */
311
+ private calculateOverlapArea;
312
+ getOutputLayout(): OutputLayout;
313
+ }
314
+
315
+ export { type Chip, type ChipId, type ChipPin, type Group, type GroupId, type GroupPin, type InputProblem, LayoutPipelineSolver, type Net, type NetId, type OutputLayout, type PinId, type Placement };