@tscircuit/matchpack 0.0.13 → 0.0.15
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/dist/index.d.ts +61 -34
- package/dist/index.js +252 -139
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -74,36 +74,12 @@ type InputProblem = {
|
|
|
74
74
|
chipGap: number;
|
|
75
75
|
/** The minimum gap between two partitions */
|
|
76
76
|
partitionGap: number;
|
|
77
|
+
decouplingCapsGap?: number;
|
|
77
78
|
inferDecouplingCaps?: boolean;
|
|
78
79
|
};
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
* Divides the layout problem into manageable sections for more efficient processing.
|
|
83
|
-
*/
|
|
84
|
-
|
|
85
|
-
declare class ChipPartitionsSolver extends BaseSolver {
|
|
86
|
-
inputProblem: InputProblem;
|
|
87
|
-
partitions: InputProblem[];
|
|
88
|
-
constructor(inputProblem: InputProblem);
|
|
89
|
-
_step(): void;
|
|
90
|
-
/**
|
|
91
|
-
* Creates partitions by finding connected components through strong pin connections
|
|
92
|
-
*/
|
|
93
|
-
private createPartitions;
|
|
94
|
-
/**
|
|
95
|
-
* Finds the owner chip of a given pin
|
|
96
|
-
*/
|
|
97
|
-
private findPinOwner;
|
|
98
|
-
/**
|
|
99
|
-
* Depth-first search to find connected components
|
|
100
|
-
*/
|
|
101
|
-
private dfs;
|
|
102
|
-
/**
|
|
103
|
-
* Creates a new InputProblem containing only the components in the given partition
|
|
104
|
-
*/
|
|
105
|
-
private createInputProblemFromPartition;
|
|
106
|
-
visualize(): GraphicsObject;
|
|
80
|
+
interface PartitionInputProblem extends InputProblem {
|
|
81
|
+
isPartition?: true;
|
|
82
|
+
partitionType?: "default" | "decoupling_caps";
|
|
107
83
|
}
|
|
108
84
|
|
|
109
85
|
/**
|
|
@@ -116,6 +92,7 @@ declare class ChipPartitionsSolver extends BaseSolver {
|
|
|
116
92
|
interface DecouplingCapGroup {
|
|
117
93
|
decouplingCapGroupId: string;
|
|
118
94
|
mainChipId: ChipId;
|
|
95
|
+
netPair: [NetId, NetId];
|
|
119
96
|
decouplingCapChipIds: ChipId[];
|
|
120
97
|
}
|
|
121
98
|
/**
|
|
@@ -128,7 +105,7 @@ declare class IdentifyDecouplingCapsSolver extends BaseSolver {
|
|
|
128
105
|
inputProblem: InputProblem;
|
|
129
106
|
queuedChips: Chip[];
|
|
130
107
|
outputDecouplingCapGroups: DecouplingCapGroup[];
|
|
131
|
-
/** Quick lookup of groups by main chip for accumulation */
|
|
108
|
+
/** Quick lookup of groups by main chip and net pair for accumulation */
|
|
132
109
|
private groupsByMainChipId;
|
|
133
110
|
constructor(inputProblem: InputProblem);
|
|
134
111
|
/** Determine if chip is a 2-pin component with restricted rotation */
|
|
@@ -139,14 +116,54 @@ declare class IdentifyDecouplingCapsSolver extends BaseSolver {
|
|
|
139
116
|
private getStronglyConnectedNeighborChips;
|
|
140
117
|
/** Find the main chip id for a decoupling capacitor candidate */
|
|
141
118
|
private findMainChipIdForCap;
|
|
142
|
-
/**
|
|
119
|
+
/** Get all net IDs connected to a pin */
|
|
120
|
+
private getNetIdsForPin;
|
|
121
|
+
/** Get a normalized, sorted pair of net IDs connected across the two pins of a capacitor chip */
|
|
122
|
+
private getNormalizedNetPair;
|
|
123
|
+
/** Adds a decoupling capacitor to the group for the given main chip and net pair */
|
|
143
124
|
private addToGroup;
|
|
125
|
+
lastChip: Chip | null;
|
|
144
126
|
_step(): void;
|
|
145
127
|
visualize(): GraphicsObject;
|
|
146
128
|
getConstructorParams(): [InputProblem];
|
|
147
129
|
computeProgress(): number;
|
|
148
130
|
}
|
|
149
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Creates partitions (small subset groups) surrounding complex chips.
|
|
134
|
+
* Divides the layout problem into manageable sections for more efficient processing.
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
declare class ChipPartitionsSolver extends BaseSolver {
|
|
138
|
+
inputProblem: InputProblem;
|
|
139
|
+
partitions: PartitionInputProblem[];
|
|
140
|
+
decouplingCapGroups?: DecouplingCapGroup[];
|
|
141
|
+
constructor({ inputProblem, decouplingCapGroups, }: {
|
|
142
|
+
inputProblem: InputProblem;
|
|
143
|
+
decouplingCapGroups?: DecouplingCapGroup[];
|
|
144
|
+
});
|
|
145
|
+
_step(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Creates partitions by:
|
|
148
|
+
* - Separating each decoupling capacitor group into its own partition (caps only, excluding the main chip)
|
|
149
|
+
* - Partitioning remaining chips by connected components through strong pin connections
|
|
150
|
+
*/
|
|
151
|
+
private createPartitions;
|
|
152
|
+
/**
|
|
153
|
+
* Finds the owner chip of a given pin
|
|
154
|
+
*/
|
|
155
|
+
private findPinOwner;
|
|
156
|
+
/**
|
|
157
|
+
* Depth-first search to find connected components
|
|
158
|
+
*/
|
|
159
|
+
private dfs;
|
|
160
|
+
/**
|
|
161
|
+
* Creates a new InputProblem containing only the components in the given partition
|
|
162
|
+
*/
|
|
163
|
+
private createInputProblemFromPartition;
|
|
164
|
+
visualize(): GraphicsObject;
|
|
165
|
+
}
|
|
166
|
+
|
|
150
167
|
type Placement = Point & {
|
|
151
168
|
ccwRotationDegrees: number;
|
|
152
169
|
};
|
|
@@ -161,10 +178,14 @@ type OutputLayout = {
|
|
|
161
178
|
*/
|
|
162
179
|
|
|
163
180
|
declare class SingleInnerPartitionPackingSolver extends BaseSolver {
|
|
164
|
-
|
|
181
|
+
partitionInputProblem: PartitionInputProblem;
|
|
165
182
|
layout: OutputLayout | null;
|
|
166
183
|
activeSubSolver: PackSolver2 | null;
|
|
167
|
-
|
|
184
|
+
pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
|
|
185
|
+
constructor(params: {
|
|
186
|
+
partitionInputProblem: PartitionInputProblem;
|
|
187
|
+
pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
|
|
188
|
+
});
|
|
168
189
|
_step(): void;
|
|
169
190
|
private createPackInput;
|
|
170
191
|
private createLayoutFromPackingResult;
|
|
@@ -188,7 +209,12 @@ declare class PackInnerPartitionsSolver extends BaseSolver {
|
|
|
188
209
|
completedSolvers: SingleInnerPartitionPackingSolver[];
|
|
189
210
|
activeSolver: SingleInnerPartitionPackingSolver | null;
|
|
190
211
|
currentPartitionIndex: number;
|
|
191
|
-
|
|
212
|
+
activeSubSolver: SingleInnerPartitionPackingSolver | null;
|
|
213
|
+
pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
|
|
214
|
+
constructor(params: {
|
|
215
|
+
partitions: InputProblem[];
|
|
216
|
+
pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
|
|
217
|
+
});
|
|
192
218
|
_step(): void;
|
|
193
219
|
visualize(): GraphicsObject;
|
|
194
220
|
getConstructorParams(): [InputProblem[]];
|
|
@@ -237,6 +263,7 @@ declare class LayoutPipelineSolver extends BaseSolver {
|
|
|
237
263
|
endTimeOfPhase: Record<string, number>;
|
|
238
264
|
timeSpentOnPhase: Record<string, number>;
|
|
239
265
|
firstIterationOfPhase: Record<string, number>;
|
|
266
|
+
pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
|
|
240
267
|
inputProblem: InputProblem;
|
|
241
268
|
chipPartitions?: ChipPartitionsSolver["partitions"];
|
|
242
269
|
packedPartitions?: PackedPartition[];
|
|
@@ -272,4 +299,4 @@ declare class LayoutPipelineSolver extends BaseSolver {
|
|
|
272
299
|
getOutputLayout(): OutputLayout;
|
|
273
300
|
}
|
|
274
301
|
|
|
275
|
-
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 };
|
|
302
|
+
export { type Chip, type ChipId, type ChipPin, type Group, type GroupId, type GroupPin, type InputProblem, LayoutPipelineSolver, type Net, type NetId, type OutputLayout, type PartitionInputProblem, type PinId, type Placement };
|
package/dist/index.js
CHANGED
|
@@ -317,21 +317,45 @@ function doBasicInputProblemLayout(inputProblem) {
|
|
|
317
317
|
var ChipPartitionsSolver = class extends BaseSolver {
|
|
318
318
|
inputProblem;
|
|
319
319
|
partitions = [];
|
|
320
|
-
|
|
320
|
+
decouplingCapGroups;
|
|
321
|
+
constructor({
|
|
322
|
+
inputProblem,
|
|
323
|
+
decouplingCapGroups
|
|
324
|
+
}) {
|
|
321
325
|
super();
|
|
322
326
|
this.inputProblem = inputProblem;
|
|
327
|
+
this.decouplingCapGroups = decouplingCapGroups;
|
|
323
328
|
}
|
|
324
329
|
_step() {
|
|
325
330
|
this.partitions = this.createPartitions(this.inputProblem);
|
|
326
331
|
this.solved = true;
|
|
327
332
|
}
|
|
328
333
|
/**
|
|
329
|
-
* Creates partitions by
|
|
334
|
+
* Creates partitions by:
|
|
335
|
+
* - Separating each decoupling capacitor group into its own partition (caps only, excluding the main chip)
|
|
336
|
+
* - Partitioning remaining chips by connected components through strong pin connections
|
|
330
337
|
*/
|
|
331
338
|
createPartitions(inputProblem) {
|
|
332
339
|
const chipIds = Object.keys(inputProblem.chipMap);
|
|
340
|
+
const decapChipIdSet = /* @__PURE__ */ new Set();
|
|
341
|
+
const decapGroupPartitions = [];
|
|
342
|
+
if (this.decouplingCapGroups && this.decouplingCapGroups.length > 0) {
|
|
343
|
+
for (const group of this.decouplingCapGroups) {
|
|
344
|
+
const capsOnly = [];
|
|
345
|
+
for (const capId of group.decouplingCapChipIds) {
|
|
346
|
+
if (inputProblem.chipMap[capId]) {
|
|
347
|
+
capsOnly.push(capId);
|
|
348
|
+
decapChipIdSet.add(capId);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (capsOnly.length > 0) {
|
|
352
|
+
decapGroupPartitions.push(capsOnly);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const nonDecapChipIds = chipIds.filter((id) => !decapChipIdSet.has(id));
|
|
333
357
|
const adjacencyMap = /* @__PURE__ */ new Map();
|
|
334
|
-
for (const chipId of
|
|
358
|
+
for (const chipId of nonDecapChipIds) {
|
|
335
359
|
adjacencyMap.set(chipId, /* @__PURE__ */ new Set());
|
|
336
360
|
}
|
|
337
361
|
for (const [connKey, isConnected] of Object.entries(
|
|
@@ -341,24 +365,31 @@ var ChipPartitionsSolver = class extends BaseSolver {
|
|
|
341
365
|
const [pin1Id, pin2Id] = connKey.split("-");
|
|
342
366
|
const owner1 = this.findPinOwner(pin1Id, inputProblem);
|
|
343
367
|
const owner2 = this.findPinOwner(pin2Id, inputProblem);
|
|
344
|
-
if (owner1 && owner2 && owner1 !== owner2) {
|
|
368
|
+
if (owner1 && owner2 && owner1 !== owner2 && !decapChipIdSet.has(owner1) && !decapChipIdSet.has(owner2)) {
|
|
345
369
|
adjacencyMap.get(owner1).add(owner2);
|
|
346
370
|
adjacencyMap.get(owner2).add(owner1);
|
|
347
371
|
}
|
|
348
372
|
}
|
|
349
373
|
const visited = /* @__PURE__ */ new Set();
|
|
350
|
-
const
|
|
351
|
-
for (const componentId of
|
|
374
|
+
const nonDecapPartitions = [];
|
|
375
|
+
for (const componentId of nonDecapChipIds) {
|
|
352
376
|
if (!visited.has(componentId)) {
|
|
353
377
|
const partition = this.dfs(componentId, adjacencyMap, visited);
|
|
354
378
|
if (partition.length > 0) {
|
|
355
|
-
|
|
379
|
+
nonDecapPartitions.push(partition);
|
|
356
380
|
}
|
|
357
381
|
}
|
|
358
382
|
}
|
|
359
|
-
return
|
|
360
|
-
|
|
361
|
-
|
|
383
|
+
return [
|
|
384
|
+
...decapGroupPartitions.map(
|
|
385
|
+
(partition) => this.createInputProblemFromPartition(partition, inputProblem, {
|
|
386
|
+
partitionType: "decoupling_caps"
|
|
387
|
+
})
|
|
388
|
+
),
|
|
389
|
+
...nonDecapPartitions.map(
|
|
390
|
+
(partition) => this.createInputProblemFromPartition(partition, inputProblem)
|
|
391
|
+
)
|
|
392
|
+
];
|
|
362
393
|
}
|
|
363
394
|
/**
|
|
364
395
|
* Finds the owner chip of a given pin
|
|
@@ -397,7 +428,7 @@ var ChipPartitionsSolver = class extends BaseSolver {
|
|
|
397
428
|
/**
|
|
398
429
|
* Creates a new InputProblem containing only the components in the given partition
|
|
399
430
|
*/
|
|
400
|
-
createInputProblemFromPartition(partition, originalProblem) {
|
|
431
|
+
createInputProblemFromPartition(partition, originalProblem, opts) {
|
|
401
432
|
const chipIds = partition;
|
|
402
433
|
const relevantPinIds = /* @__PURE__ */ new Set();
|
|
403
434
|
for (const chipId of chipIds) {
|
|
@@ -444,13 +475,14 @@ var ChipPartitionsSolver = class extends BaseSolver {
|
|
|
444
475
|
}
|
|
445
476
|
}
|
|
446
477
|
return {
|
|
478
|
+
...originalProblem,
|
|
447
479
|
chipMap,
|
|
448
480
|
chipPinMap,
|
|
449
481
|
netMap,
|
|
450
482
|
pinStrongConnMap,
|
|
451
483
|
netConnMap,
|
|
452
|
-
|
|
453
|
-
|
|
484
|
+
isPartition: true,
|
|
485
|
+
partitionType: opts?.partitionType
|
|
454
486
|
};
|
|
455
487
|
}
|
|
456
488
|
visualize() {
|
|
@@ -468,10 +500,13 @@ var ChipPartitionsSolver = class extends BaseSolver {
|
|
|
468
500
|
|
|
469
501
|
// lib/utils/getColorFromString.ts
|
|
470
502
|
var getColorFromString = (string, alpha = 1) => {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
503
|
+
let hash = 0;
|
|
504
|
+
for (let i = 0; i < string.length; i++) {
|
|
505
|
+
const char = string.charCodeAt(i);
|
|
506
|
+
hash = (hash << 5) - hash + char;
|
|
507
|
+
hash = hash & hash;
|
|
508
|
+
}
|
|
509
|
+
return `hsl(${Math.abs(hash) % 360}, 70%, 50%, ${alpha})`;
|
|
475
510
|
};
|
|
476
511
|
|
|
477
512
|
// lib/solvers/IdentifyDecouplingCapsSolver/IdentifyDecouplingCapsSolver.ts
|
|
@@ -479,7 +514,7 @@ var IdentifyDecouplingCapsSolver = class extends BaseSolver {
|
|
|
479
514
|
inputProblem;
|
|
480
515
|
queuedChips;
|
|
481
516
|
outputDecouplingCapGroups = [];
|
|
482
|
-
/** Quick lookup of groups by main chip for accumulation */
|
|
517
|
+
/** Quick lookup of groups by main chip and net pair for accumulation */
|
|
483
518
|
groupsByMainChipId = /* @__PURE__ */ new Map();
|
|
484
519
|
constructor(inputProblem) {
|
|
485
520
|
super();
|
|
@@ -539,33 +574,64 @@ var IdentifyDecouplingCapsSolver = class extends BaseSolver {
|
|
|
539
574
|
}
|
|
540
575
|
return best ? best.id : null;
|
|
541
576
|
}
|
|
542
|
-
/**
|
|
543
|
-
|
|
544
|
-
|
|
577
|
+
/** Get all net IDs connected to a pin */
|
|
578
|
+
getNetIdsForPin(pinId) {
|
|
579
|
+
const nets = /* @__PURE__ */ new Set();
|
|
580
|
+
for (const [connKey, connected] of Object.entries(
|
|
581
|
+
this.inputProblem.netConnMap
|
|
582
|
+
)) {
|
|
583
|
+
if (!connected) continue;
|
|
584
|
+
const [p, n] = connKey.split("-");
|
|
585
|
+
if (p === pinId) nets.add(n);
|
|
586
|
+
}
|
|
587
|
+
return nets;
|
|
588
|
+
}
|
|
589
|
+
/** Get a normalized, sorted pair of net IDs connected across the two pins of a capacitor chip */
|
|
590
|
+
getNormalizedNetPair(capChip) {
|
|
591
|
+
if (capChip.pins.length !== 2) return null;
|
|
592
|
+
const nets = /* @__PURE__ */ new Set();
|
|
593
|
+
for (const pinId of capChip.pins) {
|
|
594
|
+
const pinNets = this.getNetIdsForPin(pinId);
|
|
595
|
+
for (const n of pinNets) nets.add(n);
|
|
596
|
+
}
|
|
597
|
+
if (nets.size !== 2) return null;
|
|
598
|
+
const [a, b] = Array.from(nets).sort();
|
|
599
|
+
return [a, b];
|
|
600
|
+
}
|
|
601
|
+
/** Adds a decoupling capacitor to the group for the given main chip and net pair */
|
|
602
|
+
addToGroup(mainChipId, netPair, capChipId) {
|
|
603
|
+
const [n1, n2] = netPair;
|
|
604
|
+
const groupKey = `${mainChipId}__${n1}__${n2}`;
|
|
605
|
+
let group = this.groupsByMainChipId.get(groupKey);
|
|
545
606
|
if (!group) {
|
|
546
607
|
group = {
|
|
547
|
-
decouplingCapGroupId: `decap_group_${mainChipId}`,
|
|
608
|
+
decouplingCapGroupId: `decap_group_${mainChipId}__${n1}__${n2}`,
|
|
548
609
|
mainChipId,
|
|
610
|
+
netPair: [n1, n2],
|
|
549
611
|
decouplingCapChipIds: []
|
|
550
612
|
};
|
|
551
|
-
this.groupsByMainChipId.set(
|
|
613
|
+
this.groupsByMainChipId.set(groupKey, group);
|
|
552
614
|
this.outputDecouplingCapGroups.push(group);
|
|
553
615
|
}
|
|
554
616
|
if (!group.decouplingCapChipIds.includes(capChipId)) {
|
|
555
617
|
group.decouplingCapChipIds.push(capChipId);
|
|
556
618
|
}
|
|
557
619
|
}
|
|
620
|
+
lastChip = null;
|
|
558
621
|
_step() {
|
|
559
622
|
const currentChip = this.queuedChips.shift();
|
|
623
|
+
this.lastChip = currentChip ?? null;
|
|
560
624
|
if (!currentChip) {
|
|
561
625
|
this.solved = true;
|
|
562
626
|
return;
|
|
563
627
|
}
|
|
564
|
-
const
|
|
565
|
-
if (!
|
|
628
|
+
const isDecouplingCap = this.isTwoPinRestrictedRotation(currentChip) && this.pinsOnOppositeYSides(currentChip);
|
|
629
|
+
if (!isDecouplingCap) return;
|
|
566
630
|
const mainChipId = this.findMainChipIdForCap(currentChip);
|
|
567
631
|
if (!mainChipId) return;
|
|
568
|
-
this.
|
|
632
|
+
const netPair = this.getNormalizedNetPair(currentChip);
|
|
633
|
+
if (!netPair) return;
|
|
634
|
+
this.addToGroup(mainChipId, netPair, currentChip.chipId);
|
|
569
635
|
}
|
|
570
636
|
visualize() {
|
|
571
637
|
const basicLayout = doBasicInputProblemLayout(this.inputProblem);
|
|
@@ -573,38 +639,25 @@ var IdentifyDecouplingCapsSolver = class extends BaseSolver {
|
|
|
573
639
|
this.inputProblem,
|
|
574
640
|
basicLayout
|
|
575
641
|
);
|
|
576
|
-
const
|
|
642
|
+
const chipDecapGroupMap = /* @__PURE__ */ new Map();
|
|
577
643
|
for (const group of this.outputDecouplingCapGroups) {
|
|
578
|
-
|
|
579
|
-
chipRoleMap.set(group.mainChipId, { type: "main", color });
|
|
644
|
+
chipDecapGroupMap.set(group.mainChipId, group);
|
|
580
645
|
for (const capChipId of group.decouplingCapChipIds) {
|
|
581
|
-
|
|
646
|
+
chipDecapGroupMap.set(capChipId, group);
|
|
582
647
|
}
|
|
583
648
|
}
|
|
584
649
|
for (const rect of graphics.rects || []) {
|
|
585
|
-
rect.
|
|
650
|
+
if (rect.label !== this.lastChip?.chipId) {
|
|
651
|
+
rect.fill = "rgba(0,0,0,0.5)";
|
|
652
|
+
}
|
|
586
653
|
}
|
|
587
654
|
for (const rect of graphics.rects || []) {
|
|
588
655
|
const chipId = rect.label;
|
|
589
|
-
const
|
|
590
|
-
if (!
|
|
591
|
-
const alpha = role.type === "main" ? 0.18 : 0.36;
|
|
656
|
+
const group = chipDecapGroupMap.get(chipId);
|
|
657
|
+
if (!group) continue;
|
|
592
658
|
rect.label = `${rect.label}
|
|
593
|
-
${
|
|
594
|
-
rect.fill = getColorFromString(
|
|
595
|
-
}
|
|
596
|
-
if (!graphics.texts) graphics.texts = [];
|
|
597
|
-
for (const rect of graphics.rects || []) {
|
|
598
|
-
const chipId = rect.label;
|
|
599
|
-
const role = chipRoleMap.get(chipId);
|
|
600
|
-
if (!role) continue;
|
|
601
|
-
graphics.texts.push({
|
|
602
|
-
x: rect.center.x,
|
|
603
|
-
y: rect.center.y - (rect.height || 0) / 2,
|
|
604
|
-
text: role.type === "main" ? "MAIN" : "DECAP",
|
|
605
|
-
fillColor: role.type === "main" ? role.color : "rgba(0,0,0,0.6)",
|
|
606
|
-
fontSize: 8
|
|
607
|
-
});
|
|
659
|
+
${group.decouplingCapGroupId}`;
|
|
660
|
+
rect.fill = getColorFromString(group.decouplingCapGroupId, 0.8);
|
|
608
661
|
}
|
|
609
662
|
return graphics;
|
|
610
663
|
}
|
|
@@ -622,14 +675,17 @@ ${role.type}`;
|
|
|
622
675
|
import { PackSolver2 } from "calculate-packing";
|
|
623
676
|
|
|
624
677
|
// lib/utils/networkFiltering.ts
|
|
625
|
-
function createFilteredNetworkMapping(
|
|
678
|
+
function createFilteredNetworkMapping(params) {
|
|
679
|
+
const { inputProblem, pinIdToStronglyConnectedPins } = params;
|
|
626
680
|
const pinToNetworkMap = /* @__PURE__ */ new Map();
|
|
627
681
|
const filteredPins = /* @__PURE__ */ new Set();
|
|
682
|
+
let hasStrongConnections = false;
|
|
628
683
|
const strongConnectedChipSides = /* @__PURE__ */ new Map();
|
|
629
684
|
for (const [connKey, connected] of Object.entries(
|
|
630
685
|
inputProblem.pinStrongConnMap
|
|
631
686
|
)) {
|
|
632
687
|
if (!connected) continue;
|
|
688
|
+
hasStrongConnections = true;
|
|
633
689
|
const pins = connKey.split("-");
|
|
634
690
|
if (pins.length === 2 && pins[0] && pins[1]) {
|
|
635
691
|
const pin1 = inputProblem.chipPinMap[pins[0]];
|
|
@@ -652,45 +708,59 @@ function createFilteredNetworkMapping(inputProblem) {
|
|
|
652
708
|
}
|
|
653
709
|
}
|
|
654
710
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
711
|
+
if (hasStrongConnections) {
|
|
712
|
+
for (const [connKey, connected] of Object.entries(
|
|
713
|
+
inputProblem.netConnMap
|
|
714
|
+
)) {
|
|
715
|
+
if (!connected) continue;
|
|
716
|
+
const [pinId, netId] = connKey.split("-");
|
|
717
|
+
if (pinId && netId) {
|
|
718
|
+
filteredPins.add(pinId);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
} else {
|
|
722
|
+
for (const [connKey, connected] of Object.entries(
|
|
723
|
+
inputProblem.netConnMap
|
|
724
|
+
)) {
|
|
725
|
+
if (!connected) continue;
|
|
726
|
+
const [pinId, netId] = connKey.split("-");
|
|
727
|
+
if (pinId && netId) {
|
|
728
|
+
const pin = inputProblem.chipPinMap[pinId];
|
|
729
|
+
if (!pin) continue;
|
|
730
|
+
const chipId = pinId.split(".")[0];
|
|
731
|
+
let shouldIncludeInNetwork = true;
|
|
732
|
+
for (const [
|
|
733
|
+
strongKey,
|
|
734
|
+
strongSides
|
|
735
|
+
] of strongConnectedChipSides.entries()) {
|
|
736
|
+
const [fromChip, toChip] = strongKey.split("-");
|
|
737
|
+
if (fromChip === chipId) {
|
|
738
|
+
for (const [otherConnKey, otherConnected] of Object.entries(
|
|
739
|
+
inputProblem.netConnMap
|
|
740
|
+
)) {
|
|
741
|
+
if (!otherConnected) continue;
|
|
742
|
+
const [otherPinId, otherNetId] = otherConnKey.split("-");
|
|
743
|
+
if (otherNetId === netId && otherPinId && otherPinId !== pinId) {
|
|
744
|
+
const otherPin = inputProblem.chipPinMap[otherPinId];
|
|
745
|
+
if (!otherPin) continue;
|
|
746
|
+
const otherChipId = otherPinId.split(".")[0];
|
|
747
|
+
if (otherChipId === toChip) {
|
|
748
|
+
if (!strongSides.has(otherPin.side)) {
|
|
749
|
+
shouldIncludeInNetwork = false;
|
|
750
|
+
break;
|
|
751
|
+
}
|
|
682
752
|
}
|
|
683
753
|
}
|
|
684
754
|
}
|
|
685
755
|
}
|
|
686
756
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
757
|
+
if (shouldIncludeInNetwork) {
|
|
758
|
+
pinToNetworkMap.set(pinId, netId);
|
|
759
|
+
} else {
|
|
760
|
+
const disconnectedNetworkId = `${pinId}_opposite-strong-side-disconnected`;
|
|
761
|
+
pinToNetworkMap.set(pinId, disconnectedNetworkId);
|
|
762
|
+
filteredPins.add(pinId);
|
|
763
|
+
}
|
|
694
764
|
}
|
|
695
765
|
}
|
|
696
766
|
}
|
|
@@ -736,11 +806,13 @@ var getPadsBoundingBox = (pads) => {
|
|
|
736
806
|
// lib/solvers/PackInnerPartitionsSolver/SingleInnerPartitionPackingSolver.ts
|
|
737
807
|
var PIN_SIZE = 0.1;
|
|
738
808
|
var SingleInnerPartitionPackingSolver = class extends BaseSolver {
|
|
739
|
-
|
|
809
|
+
partitionInputProblem;
|
|
740
810
|
layout = null;
|
|
741
|
-
|
|
811
|
+
pinIdToStronglyConnectedPins;
|
|
812
|
+
constructor(params) {
|
|
742
813
|
super();
|
|
743
|
-
this.
|
|
814
|
+
this.partitionInputProblem = params.partitionInputProblem;
|
|
815
|
+
this.pinIdToStronglyConnectedPins = params.pinIdToStronglyConnectedPins;
|
|
744
816
|
}
|
|
745
817
|
_step() {
|
|
746
818
|
if (!this.activeSubSolver) {
|
|
@@ -763,53 +835,55 @@ var SingleInnerPartitionPackingSolver = class extends BaseSolver {
|
|
|
763
835
|
}
|
|
764
836
|
}
|
|
765
837
|
createPackInput() {
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
offset: { x: pin.offset.x, y: pin.offset.y },
|
|
779
|
-
size: { x: PIN_SIZE, y: PIN_SIZE }
|
|
780
|
-
// Small size for pins
|
|
781
|
-
});
|
|
782
|
-
}
|
|
783
|
-
const padsBoundingBox = getPadsBoundingBox(pads);
|
|
784
|
-
const padsBoundingBoxSize = {
|
|
785
|
-
x: padsBoundingBox.maxX - padsBoundingBox.minX,
|
|
786
|
-
y: padsBoundingBox.maxY - padsBoundingBox.minY
|
|
787
|
-
};
|
|
838
|
+
const pinToNetworkMap = createFilteredNetworkMapping({
|
|
839
|
+
inputProblem: this.partitionInputProblem,
|
|
840
|
+
pinIdToStronglyConnectedPins: this.pinIdToStronglyConnectedPins
|
|
841
|
+
}).pinToNetworkMap;
|
|
842
|
+
const packComponents = Object.entries(
|
|
843
|
+
this.partitionInputProblem.chipMap
|
|
844
|
+
).map(([chipId, chip]) => {
|
|
845
|
+
const pads = [];
|
|
846
|
+
for (const pinId of chip.pins) {
|
|
847
|
+
const pin = this.partitionInputProblem.chipPinMap[pinId];
|
|
848
|
+
if (!pin) continue;
|
|
849
|
+
const networkId = pinToNetworkMap.get(pinId) || `${pinId}_isolated`;
|
|
788
850
|
pads.push({
|
|
789
|
-
padId:
|
|
790
|
-
networkId
|
|
851
|
+
padId: pinId,
|
|
852
|
+
networkId,
|
|
791
853
|
type: "rect",
|
|
792
|
-
offset: { x:
|
|
793
|
-
size: {
|
|
794
|
-
|
|
795
|
-
y: Math.max(padsBoundingBoxSize.y, chip.size.y)
|
|
796
|
-
}
|
|
854
|
+
offset: { x: pin.offset.x, y: pin.offset.y },
|
|
855
|
+
size: { x: PIN_SIZE, y: PIN_SIZE }
|
|
856
|
+
// Small size for pins
|
|
797
857
|
});
|
|
798
|
-
return {
|
|
799
|
-
componentId: chipId,
|
|
800
|
-
pads,
|
|
801
|
-
availableRotationDegrees: chip.availableRotations || [
|
|
802
|
-
0,
|
|
803
|
-
90,
|
|
804
|
-
180,
|
|
805
|
-
270
|
|
806
|
-
]
|
|
807
|
-
};
|
|
808
858
|
}
|
|
809
|
-
|
|
859
|
+
const padsBoundingBox = getPadsBoundingBox(pads);
|
|
860
|
+
const padsBoundingBoxSize = {
|
|
861
|
+
x: padsBoundingBox.maxX - padsBoundingBox.minX,
|
|
862
|
+
y: padsBoundingBox.maxY - padsBoundingBox.minY
|
|
863
|
+
};
|
|
864
|
+
pads.push({
|
|
865
|
+
padId: `${chipId}_body`,
|
|
866
|
+
networkId: `${chipId}_body_disconnected`,
|
|
867
|
+
type: "rect",
|
|
868
|
+
offset: { x: 0, y: 0 },
|
|
869
|
+
size: {
|
|
870
|
+
x: Math.max(padsBoundingBoxSize.x, chip.size.x),
|
|
871
|
+
y: Math.max(padsBoundingBoxSize.y, chip.size.y)
|
|
872
|
+
}
|
|
873
|
+
});
|
|
874
|
+
return {
|
|
875
|
+
componentId: chipId,
|
|
876
|
+
pads,
|
|
877
|
+
availableRotationDegrees: chip.availableRotations || [0, 90, 180, 270]
|
|
878
|
+
};
|
|
879
|
+
});
|
|
880
|
+
let minGap = this.partitionInputProblem.chipGap;
|
|
881
|
+
if (this.partitionInputProblem.partitionType === "decoupling_caps") {
|
|
882
|
+
minGap = this.partitionInputProblem.decouplingCapsGap ?? minGap;
|
|
883
|
+
}
|
|
810
884
|
return {
|
|
811
885
|
components: packComponents,
|
|
812
|
-
minGap
|
|
886
|
+
minGap,
|
|
813
887
|
packOrderStrategy: "largest_to_smallest",
|
|
814
888
|
packPlacementStrategy: "minimum_closest_sum_squared_distance"
|
|
815
889
|
};
|
|
@@ -834,13 +908,13 @@ var SingleInnerPartitionPackingSolver = class extends BaseSolver {
|
|
|
834
908
|
return this.activeSubSolver.visualize();
|
|
835
909
|
}
|
|
836
910
|
if (!this.layout) {
|
|
837
|
-
const basicLayout = doBasicInputProblemLayout(this.
|
|
838
|
-
return visualizeInputProblem(this.
|
|
911
|
+
const basicLayout = doBasicInputProblemLayout(this.partitionInputProblem);
|
|
912
|
+
return visualizeInputProblem(this.partitionInputProblem, basicLayout);
|
|
839
913
|
}
|
|
840
|
-
return visualizeInputProblem(this.
|
|
914
|
+
return visualizeInputProblem(this.partitionInputProblem, this.layout);
|
|
841
915
|
}
|
|
842
916
|
getConstructorParams() {
|
|
843
|
-
return [this.
|
|
917
|
+
return [this.partitionInputProblem];
|
|
844
918
|
}
|
|
845
919
|
};
|
|
846
920
|
|
|
@@ -852,9 +926,11 @@ var PackInnerPartitionsSolver = class extends BaseSolver {
|
|
|
852
926
|
completedSolvers = [];
|
|
853
927
|
activeSolver = null;
|
|
854
928
|
currentPartitionIndex = 0;
|
|
855
|
-
|
|
929
|
+
pinIdToStronglyConnectedPins;
|
|
930
|
+
constructor(params) {
|
|
856
931
|
super();
|
|
857
|
-
this.partitions = partitions;
|
|
932
|
+
this.partitions = params.partitions;
|
|
933
|
+
this.pinIdToStronglyConnectedPins = params.pinIdToStronglyConnectedPins;
|
|
858
934
|
}
|
|
859
935
|
_step() {
|
|
860
936
|
if (this.currentPartitionIndex >= this.partitions.length) {
|
|
@@ -863,9 +939,10 @@ var PackInnerPartitionsSolver = class extends BaseSolver {
|
|
|
863
939
|
}
|
|
864
940
|
if (!this.activeSolver) {
|
|
865
941
|
const currentPartition = this.partitions[this.currentPartitionIndex];
|
|
866
|
-
this.activeSolver = new SingleInnerPartitionPackingSolver(
|
|
867
|
-
currentPartition
|
|
868
|
-
|
|
942
|
+
this.activeSolver = new SingleInnerPartitionPackingSolver({
|
|
943
|
+
partitionInputProblem: currentPartition,
|
|
944
|
+
pinIdToStronglyConnectedPins: this.pinIdToStronglyConnectedPins
|
|
945
|
+
});
|
|
869
946
|
this.activeSubSolver = this.activeSolver;
|
|
870
947
|
}
|
|
871
948
|
this.activeSolver.step();
|
|
@@ -1179,6 +1256,29 @@ var PartitionPackingSolver = class extends BaseSolver {
|
|
|
1179
1256
|
}
|
|
1180
1257
|
};
|
|
1181
1258
|
|
|
1259
|
+
// lib/solvers/LayoutPipelineSolver/getPinIdToStronglyConnectedPinsObj.ts
|
|
1260
|
+
var getPinIdToStronglyConnectedPinsObj = (inputProblem) => {
|
|
1261
|
+
const pinIdToStronglyConnectedPins = {};
|
|
1262
|
+
const pinIds = Object.keys(inputProblem.chipPinMap);
|
|
1263
|
+
for (let i = 0; i < pinIds.length; i++) {
|
|
1264
|
+
for (let j = i + 1; j < pinIds.length; j++) {
|
|
1265
|
+
const pinId1 = pinIds[i];
|
|
1266
|
+
const pinId2 = pinIds[j];
|
|
1267
|
+
if (inputProblem.pinStrongConnMap[`${pinId1}-${pinId2}`] || inputProblem.pinStrongConnMap[`${pinId2}-${pinId1}`]) {
|
|
1268
|
+
pinIdToStronglyConnectedPins[pinId1] ??= [];
|
|
1269
|
+
pinIdToStronglyConnectedPins[pinId2] ??= [];
|
|
1270
|
+
pinIdToStronglyConnectedPins[pinId1].push(
|
|
1271
|
+
inputProblem.chipPinMap[pinId2]
|
|
1272
|
+
);
|
|
1273
|
+
pinIdToStronglyConnectedPins[pinId2].push(
|
|
1274
|
+
inputProblem.chipPinMap[pinId1]
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return pinIdToStronglyConnectedPins;
|
|
1280
|
+
};
|
|
1281
|
+
|
|
1182
1282
|
// lib/solvers/LayoutPipelineSolver/LayoutPipelineSolver.ts
|
|
1183
1283
|
function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
|
|
1184
1284
|
return {
|
|
@@ -1197,6 +1297,8 @@ var LayoutPipelineSolver = class extends BaseSolver {
|
|
|
1197
1297
|
endTimeOfPhase;
|
|
1198
1298
|
timeSpentOnPhase;
|
|
1199
1299
|
firstIterationOfPhase;
|
|
1300
|
+
// Computed utility objects
|
|
1301
|
+
pinIdToStronglyConnectedPins;
|
|
1200
1302
|
inputProblem;
|
|
1201
1303
|
chipPartitions;
|
|
1202
1304
|
packedPartitions;
|
|
@@ -1213,7 +1315,12 @@ var LayoutPipelineSolver = class extends BaseSolver {
|
|
|
1213
1315
|
definePipelineStep(
|
|
1214
1316
|
"chipPartitionsSolver",
|
|
1215
1317
|
ChipPartitionsSolver,
|
|
1216
|
-
() => [
|
|
1318
|
+
() => [
|
|
1319
|
+
{
|
|
1320
|
+
inputProblem: this.inputProblem,
|
|
1321
|
+
decouplingCapGroups: this.identifyDecouplingCapsSolver?.outputDecouplingCapGroups
|
|
1322
|
+
}
|
|
1323
|
+
],
|
|
1217
1324
|
{
|
|
1218
1325
|
onSolved: (_layoutSolver) => {
|
|
1219
1326
|
this.chipPartitions = this.chipPartitionsSolver.partitions;
|
|
@@ -1223,7 +1330,12 @@ var LayoutPipelineSolver = class extends BaseSolver {
|
|
|
1223
1330
|
definePipelineStep(
|
|
1224
1331
|
"packInnerPartitionsSolver",
|
|
1225
1332
|
PackInnerPartitionsSolver,
|
|
1226
|
-
() => [
|
|
1333
|
+
() => [
|
|
1334
|
+
{
|
|
1335
|
+
partitions: this.chipPartitions,
|
|
1336
|
+
pinIdToStronglyConnectedPins: this.pinIdToStronglyConnectedPins
|
|
1337
|
+
}
|
|
1338
|
+
],
|
|
1227
1339
|
{
|
|
1228
1340
|
onSolved: (_solver) => {
|
|
1229
1341
|
this.packedPartitions = this.packInnerPartitionsSolver.packedPartitions;
|
|
@@ -1253,6 +1365,7 @@ var LayoutPipelineSolver = class extends BaseSolver {
|
|
|
1253
1365
|
this.endTimeOfPhase = {};
|
|
1254
1366
|
this.timeSpentOnPhase = {};
|
|
1255
1367
|
this.firstIterationOfPhase = {};
|
|
1368
|
+
this.pinIdToStronglyConnectedPins = getPinIdToStronglyConnectedPinsObj(inputProblem);
|
|
1256
1369
|
}
|
|
1257
1370
|
currentPipelineStepIndex = 0;
|
|
1258
1371
|
_step() {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@tscircuit/matchpack",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.15",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
8
8
|
],
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"bpc-graph": "^0.0.66",
|
|
24
24
|
"calculate-packing": "^0.0.31",
|
|
25
25
|
"circuit-json": "^0.0.226",
|
|
26
|
-
"graphics-debug": "^0.0.
|
|
26
|
+
"graphics-debug": "^0.0.64",
|
|
27
27
|
"react-cosmos": "^7.0.0",
|
|
28
28
|
"react-cosmos-plugin-vite": "^7.0.0",
|
|
29
29
|
"tscircuit": "^0.0.593",
|