@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.
Files changed (3) hide show
  1. package/dist/index.d.ts +61 -34
  2. package/dist/index.js +252 -139
  3. 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
- * 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;
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
- /** Adds a decoupling capacitor to the group for the given main chip */
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
- inputProblem: InputProblem;
181
+ partitionInputProblem: PartitionInputProblem;
165
182
  layout: OutputLayout | null;
166
183
  activeSubSolver: PackSolver2 | null;
167
- constructor(inputProblem: InputProblem);
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
- constructor(partitions: InputProblem[]);
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
- constructor(inputProblem) {
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 finding connected components through strong pin connections
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 chipIds) {
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 partitions = [];
351
- for (const componentId of chipIds) {
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
- partitions.push(partition);
379
+ nonDecapPartitions.push(partition);
356
380
  }
357
381
  }
358
382
  }
359
- return partitions.map(
360
- (partition) => this.createInputProblemFromPartition(partition, inputProblem)
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
- chipGap: originalProblem.chipGap,
453
- partitionGap: originalProblem.partitionGap
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
- const hash = string.split("").reduce((acc, char) => {
472
- return acc * 31 + char.charCodeAt(0);
473
- }, 0);
474
- return `hsl(${hash % 360}, 100%, 50%, ${alpha})`;
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
- /** Adds a decoupling capacitor to the group for the given main chip */
543
- addToGroup(mainChipId, capChipId) {
544
- let group = this.groupsByMainChipId.get(mainChipId);
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(mainChipId, group);
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 candidate = this.isTwoPinRestrictedRotation(currentChip) && this.pinsOnOppositeYSides(currentChip);
565
- if (!candidate) return;
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.addToGroup(mainChipId, currentChip.chipId);
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 chipRoleMap = /* @__PURE__ */ new Map();
642
+ const chipDecapGroupMap = /* @__PURE__ */ new Map();
577
643
  for (const group of this.outputDecouplingCapGroups) {
578
- const color = getColorFromString(group.mainChipId, 0.8);
579
- chipRoleMap.set(group.mainChipId, { type: "main", color });
644
+ chipDecapGroupMap.set(group.mainChipId, group);
580
645
  for (const capChipId of group.decouplingCapChipIds) {
581
- chipRoleMap.set(capChipId, { type: "decap", color });
646
+ chipDecapGroupMap.set(capChipId, group);
582
647
  }
583
648
  }
584
649
  for (const rect of graphics.rects || []) {
585
- rect.fill = "rgba(0,0,0,0.5)";
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 role = chipRoleMap.get(chipId);
590
- if (!role) continue;
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
- ${role.type}`;
594
- rect.fill = getColorFromString(role.color, alpha);
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(inputProblem) {
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
- for (const [connKey, connected] of Object.entries(inputProblem.netConnMap)) {
656
- if (!connected) continue;
657
- const [pinId, netId] = connKey.split("-");
658
- if (pinId && netId) {
659
- const pin = inputProblem.chipPinMap[pinId];
660
- if (!pin) continue;
661
- const chipId = pinId.split(".")[0];
662
- let shouldIncludeInNetwork = true;
663
- for (const [
664
- strongKey,
665
- strongSides
666
- ] of strongConnectedChipSides.entries()) {
667
- const [fromChip, toChip] = strongKey.split("-");
668
- if (fromChip === chipId) {
669
- for (const [otherConnKey, otherConnected] of Object.entries(
670
- inputProblem.netConnMap
671
- )) {
672
- if (!otherConnected) continue;
673
- const [otherPinId, otherNetId] = otherConnKey.split("-");
674
- if (otherNetId === netId && otherPinId && otherPinId !== pinId) {
675
- const otherPin = inputProblem.chipPinMap[otherPinId];
676
- if (!otherPin) continue;
677
- const otherChipId = otherPinId.split(".")[0];
678
- if (otherChipId === toChip) {
679
- if (!strongSides.has(otherPin.side)) {
680
- shouldIncludeInNetwork = false;
681
- break;
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
- if (shouldIncludeInNetwork) {
689
- pinToNetworkMap.set(pinId, netId);
690
- } else {
691
- const disconnectedNetworkId = `${pinId}_opposite-strong-side-disconnected`;
692
- pinToNetworkMap.set(pinId, disconnectedNetworkId);
693
- filteredPins.add(pinId);
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
- inputProblem;
809
+ partitionInputProblem;
740
810
  layout = null;
741
- constructor(inputProblem) {
811
+ pinIdToStronglyConnectedPins;
812
+ constructor(params) {
742
813
  super();
743
- this.inputProblem = inputProblem;
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 { pinToNetworkMap } = createFilteredNetworkMapping(this.inputProblem);
767
- const packComponents = Object.entries(this.inputProblem.chipMap).map(
768
- ([chipId, chip]) => {
769
- const pads = [];
770
- for (const pinId of chip.pins) {
771
- const pin = this.inputProblem.chipPinMap[pinId];
772
- if (!pin) continue;
773
- const networkId = pinToNetworkMap.get(pinId) || `${pinId}_isolated`;
774
- pads.push({
775
- padId: pinId,
776
- networkId,
777
- type: "rect",
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: `${chipId}_body`,
790
- networkId: `${chipId}_body_disconnected`,
851
+ padId: pinId,
852
+ networkId,
791
853
  type: "rect",
792
- offset: { x: 0, y: 0 },
793
- size: {
794
- x: Math.max(padsBoundingBoxSize.x, chip.size.x),
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: this.inputProblem.chipGap,
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.inputProblem);
838
- return visualizeInputProblem(this.inputProblem, basicLayout);
911
+ const basicLayout = doBasicInputProblemLayout(this.partitionInputProblem);
912
+ return visualizeInputProblem(this.partitionInputProblem, basicLayout);
839
913
  }
840
- return visualizeInputProblem(this.inputProblem, this.layout);
914
+ return visualizeInputProblem(this.partitionInputProblem, this.layout);
841
915
  }
842
916
  getConstructorParams() {
843
- return [this.inputProblem];
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
- constructor(partitions) {
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
- () => [this.inputProblem],
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
- () => [this.chipPartitions || [this.inputProblem]],
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.13",
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.62",
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",