@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 +24 -0
- package/dist/index.d.ts +315 -0
- package/dist/index.js +22390 -0
- package/package.json +34 -0
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
|
package/dist/index.d.ts
ADDED
|
@@ -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 };
|