@tscircuit/matchpack 0.0.13 → 0.0.14
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 +43 -31
- package/dist/index.js +96 -45
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -77,35 +77,6 @@ type InputProblem = {
|
|
|
77
77
|
inferDecouplingCaps?: boolean;
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
/**
|
|
81
|
-
* Creates partitions (small subset groups) surrounding complex chips.
|
|
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;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
80
|
/**
|
|
110
81
|
* Identifies decoupling capacitor groups based on specific criteria:
|
|
111
82
|
* 1. Component has exactly 2 pins and restricted rotation (0/180 only or no rotation)
|
|
@@ -116,6 +87,7 @@ declare class ChipPartitionsSolver extends BaseSolver {
|
|
|
116
87
|
interface DecouplingCapGroup {
|
|
117
88
|
decouplingCapGroupId: string;
|
|
118
89
|
mainChipId: ChipId;
|
|
90
|
+
netPair: [NetId, NetId];
|
|
119
91
|
decouplingCapChipIds: ChipId[];
|
|
120
92
|
}
|
|
121
93
|
/**
|
|
@@ -128,7 +100,7 @@ declare class IdentifyDecouplingCapsSolver extends BaseSolver {
|
|
|
128
100
|
inputProblem: InputProblem;
|
|
129
101
|
queuedChips: Chip[];
|
|
130
102
|
outputDecouplingCapGroups: DecouplingCapGroup[];
|
|
131
|
-
/** Quick lookup of groups by main chip for accumulation */
|
|
103
|
+
/** Quick lookup of groups by main chip and net pair for accumulation */
|
|
132
104
|
private groupsByMainChipId;
|
|
133
105
|
constructor(inputProblem: InputProblem);
|
|
134
106
|
/** Determine if chip is a 2-pin component with restricted rotation */
|
|
@@ -139,14 +111,54 @@ declare class IdentifyDecouplingCapsSolver extends BaseSolver {
|
|
|
139
111
|
private getStronglyConnectedNeighborChips;
|
|
140
112
|
/** Find the main chip id for a decoupling capacitor candidate */
|
|
141
113
|
private findMainChipIdForCap;
|
|
142
|
-
/**
|
|
114
|
+
/** Get all net IDs connected to a pin */
|
|
115
|
+
private getNetIdsForPin;
|
|
116
|
+
/** Get a normalized, sorted pair of net IDs connected across the two pins of a capacitor chip */
|
|
117
|
+
private getNormalizedNetPair;
|
|
118
|
+
/** Adds a decoupling capacitor to the group for the given main chip and net pair */
|
|
143
119
|
private addToGroup;
|
|
120
|
+
lastChip: Chip | null;
|
|
144
121
|
_step(): void;
|
|
145
122
|
visualize(): GraphicsObject;
|
|
146
123
|
getConstructorParams(): [InputProblem];
|
|
147
124
|
computeProgress(): number;
|
|
148
125
|
}
|
|
149
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Creates partitions (small subset groups) surrounding complex chips.
|
|
129
|
+
* Divides the layout problem into manageable sections for more efficient processing.
|
|
130
|
+
*/
|
|
131
|
+
|
|
132
|
+
declare class ChipPartitionsSolver extends BaseSolver {
|
|
133
|
+
inputProblem: InputProblem;
|
|
134
|
+
partitions: InputProblem[];
|
|
135
|
+
decouplingCapGroups?: DecouplingCapGroup[];
|
|
136
|
+
constructor({ inputProblem, decouplingCapGroups, }: {
|
|
137
|
+
inputProblem: InputProblem;
|
|
138
|
+
decouplingCapGroups?: DecouplingCapGroup[];
|
|
139
|
+
});
|
|
140
|
+
_step(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Creates partitions by:
|
|
143
|
+
* - Separating each decoupling capacitor group into its own partition (caps only, excluding the main chip)
|
|
144
|
+
* - Partitioning remaining chips by connected components through strong pin connections
|
|
145
|
+
*/
|
|
146
|
+
private createPartitions;
|
|
147
|
+
/**
|
|
148
|
+
* Finds the owner chip of a given pin
|
|
149
|
+
*/
|
|
150
|
+
private findPinOwner;
|
|
151
|
+
/**
|
|
152
|
+
* Depth-first search to find connected components
|
|
153
|
+
*/
|
|
154
|
+
private dfs;
|
|
155
|
+
/**
|
|
156
|
+
* Creates a new InputProblem containing only the components in the given partition
|
|
157
|
+
*/
|
|
158
|
+
private createInputProblemFromPartition;
|
|
159
|
+
visualize(): GraphicsObject;
|
|
160
|
+
}
|
|
161
|
+
|
|
150
162
|
type Placement = Point & {
|
|
151
163
|
ccwRotationDegrees: number;
|
|
152
164
|
};
|
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,22 +365,23 @@ 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
|
-
|
|
383
|
+
const allPartitions = [...decapGroupPartitions, ...nonDecapPartitions];
|
|
384
|
+
return allPartitions.map(
|
|
360
385
|
(partition) => this.createInputProblemFromPartition(partition, inputProblem)
|
|
361
386
|
);
|
|
362
387
|
}
|
|
@@ -468,10 +493,13 @@ var ChipPartitionsSolver = class extends BaseSolver {
|
|
|
468
493
|
|
|
469
494
|
// lib/utils/getColorFromString.ts
|
|
470
495
|
var getColorFromString = (string, alpha = 1) => {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
496
|
+
let hash = 0;
|
|
497
|
+
for (let i = 0; i < string.length; i++) {
|
|
498
|
+
const char = string.charCodeAt(i);
|
|
499
|
+
hash = (hash << 5) - hash + char;
|
|
500
|
+
hash = hash & hash;
|
|
501
|
+
}
|
|
502
|
+
return `hsl(${Math.abs(hash) % 360}, 70%, 50%, ${alpha})`;
|
|
475
503
|
};
|
|
476
504
|
|
|
477
505
|
// lib/solvers/IdentifyDecouplingCapsSolver/IdentifyDecouplingCapsSolver.ts
|
|
@@ -479,7 +507,7 @@ var IdentifyDecouplingCapsSolver = class extends BaseSolver {
|
|
|
479
507
|
inputProblem;
|
|
480
508
|
queuedChips;
|
|
481
509
|
outputDecouplingCapGroups = [];
|
|
482
|
-
/** Quick lookup of groups by main chip for accumulation */
|
|
510
|
+
/** Quick lookup of groups by main chip and net pair for accumulation */
|
|
483
511
|
groupsByMainChipId = /* @__PURE__ */ new Map();
|
|
484
512
|
constructor(inputProblem) {
|
|
485
513
|
super();
|
|
@@ -539,33 +567,64 @@ var IdentifyDecouplingCapsSolver = class extends BaseSolver {
|
|
|
539
567
|
}
|
|
540
568
|
return best ? best.id : null;
|
|
541
569
|
}
|
|
542
|
-
/**
|
|
543
|
-
|
|
544
|
-
|
|
570
|
+
/** Get all net IDs connected to a pin */
|
|
571
|
+
getNetIdsForPin(pinId) {
|
|
572
|
+
const nets = /* @__PURE__ */ new Set();
|
|
573
|
+
for (const [connKey, connected] of Object.entries(
|
|
574
|
+
this.inputProblem.netConnMap
|
|
575
|
+
)) {
|
|
576
|
+
if (!connected) continue;
|
|
577
|
+
const [p, n] = connKey.split("-");
|
|
578
|
+
if (p === pinId) nets.add(n);
|
|
579
|
+
}
|
|
580
|
+
return nets;
|
|
581
|
+
}
|
|
582
|
+
/** Get a normalized, sorted pair of net IDs connected across the two pins of a capacitor chip */
|
|
583
|
+
getNormalizedNetPair(capChip) {
|
|
584
|
+
if (capChip.pins.length !== 2) return null;
|
|
585
|
+
const nets = /* @__PURE__ */ new Set();
|
|
586
|
+
for (const pinId of capChip.pins) {
|
|
587
|
+
const pinNets = this.getNetIdsForPin(pinId);
|
|
588
|
+
for (const n of pinNets) nets.add(n);
|
|
589
|
+
}
|
|
590
|
+
if (nets.size !== 2) return null;
|
|
591
|
+
const [a, b] = Array.from(nets).sort();
|
|
592
|
+
return [a, b];
|
|
593
|
+
}
|
|
594
|
+
/** Adds a decoupling capacitor to the group for the given main chip and net pair */
|
|
595
|
+
addToGroup(mainChipId, netPair, capChipId) {
|
|
596
|
+
const [n1, n2] = netPair;
|
|
597
|
+
const groupKey = `${mainChipId}__${n1}__${n2}`;
|
|
598
|
+
let group = this.groupsByMainChipId.get(groupKey);
|
|
545
599
|
if (!group) {
|
|
546
600
|
group = {
|
|
547
|
-
decouplingCapGroupId: `decap_group_${mainChipId}`,
|
|
601
|
+
decouplingCapGroupId: `decap_group_${mainChipId}__${n1}__${n2}`,
|
|
548
602
|
mainChipId,
|
|
603
|
+
netPair: [n1, n2],
|
|
549
604
|
decouplingCapChipIds: []
|
|
550
605
|
};
|
|
551
|
-
this.groupsByMainChipId.set(
|
|
606
|
+
this.groupsByMainChipId.set(groupKey, group);
|
|
552
607
|
this.outputDecouplingCapGroups.push(group);
|
|
553
608
|
}
|
|
554
609
|
if (!group.decouplingCapChipIds.includes(capChipId)) {
|
|
555
610
|
group.decouplingCapChipIds.push(capChipId);
|
|
556
611
|
}
|
|
557
612
|
}
|
|
613
|
+
lastChip = null;
|
|
558
614
|
_step() {
|
|
559
615
|
const currentChip = this.queuedChips.shift();
|
|
616
|
+
this.lastChip = currentChip ?? null;
|
|
560
617
|
if (!currentChip) {
|
|
561
618
|
this.solved = true;
|
|
562
619
|
return;
|
|
563
620
|
}
|
|
564
|
-
const
|
|
565
|
-
if (!
|
|
621
|
+
const isDecouplingCap = this.isTwoPinRestrictedRotation(currentChip) && this.pinsOnOppositeYSides(currentChip);
|
|
622
|
+
if (!isDecouplingCap) return;
|
|
566
623
|
const mainChipId = this.findMainChipIdForCap(currentChip);
|
|
567
624
|
if (!mainChipId) return;
|
|
568
|
-
this.
|
|
625
|
+
const netPair = this.getNormalizedNetPair(currentChip);
|
|
626
|
+
if (!netPair) return;
|
|
627
|
+
this.addToGroup(mainChipId, netPair, currentChip.chipId);
|
|
569
628
|
}
|
|
570
629
|
visualize() {
|
|
571
630
|
const basicLayout = doBasicInputProblemLayout(this.inputProblem);
|
|
@@ -573,38 +632,25 @@ var IdentifyDecouplingCapsSolver = class extends BaseSolver {
|
|
|
573
632
|
this.inputProblem,
|
|
574
633
|
basicLayout
|
|
575
634
|
);
|
|
576
|
-
const
|
|
635
|
+
const chipDecapGroupMap = /* @__PURE__ */ new Map();
|
|
577
636
|
for (const group of this.outputDecouplingCapGroups) {
|
|
578
|
-
|
|
579
|
-
chipRoleMap.set(group.mainChipId, { type: "main", color });
|
|
637
|
+
chipDecapGroupMap.set(group.mainChipId, group);
|
|
580
638
|
for (const capChipId of group.decouplingCapChipIds) {
|
|
581
|
-
|
|
639
|
+
chipDecapGroupMap.set(capChipId, group);
|
|
582
640
|
}
|
|
583
641
|
}
|
|
584
642
|
for (const rect of graphics.rects || []) {
|
|
585
|
-
rect.
|
|
643
|
+
if (rect.label !== this.lastChip?.chipId) {
|
|
644
|
+
rect.fill = "rgba(0,0,0,0.5)";
|
|
645
|
+
}
|
|
586
646
|
}
|
|
587
647
|
for (const rect of graphics.rects || []) {
|
|
588
648
|
const chipId = rect.label;
|
|
589
|
-
const
|
|
590
|
-
if (!
|
|
591
|
-
const alpha = role.type === "main" ? 0.18 : 0.36;
|
|
649
|
+
const group = chipDecapGroupMap.get(chipId);
|
|
650
|
+
if (!group) continue;
|
|
592
651
|
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
|
-
});
|
|
652
|
+
${group.decouplingCapGroupId}`;
|
|
653
|
+
rect.fill = getColorFromString(group.decouplingCapGroupId, 0.8);
|
|
608
654
|
}
|
|
609
655
|
return graphics;
|
|
610
656
|
}
|
|
@@ -1213,7 +1259,12 @@ var LayoutPipelineSolver = class extends BaseSolver {
|
|
|
1213
1259
|
definePipelineStep(
|
|
1214
1260
|
"chipPartitionsSolver",
|
|
1215
1261
|
ChipPartitionsSolver,
|
|
1216
|
-
() => [
|
|
1262
|
+
() => [
|
|
1263
|
+
{
|
|
1264
|
+
inputProblem: this.inputProblem,
|
|
1265
|
+
decouplingCapGroups: this.identifyDecouplingCapsSolver?.outputDecouplingCapGroups
|
|
1266
|
+
}
|
|
1267
|
+
],
|
|
1217
1268
|
{
|
|
1218
1269
|
onSolved: (_layoutSolver) => {
|
|
1219
1270
|
this.chipPartitions = this.chipPartitionsSolver.partitions;
|
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.14",
|
|
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",
|