@tscircuit/matchpack 0.0.14 → 0.0.16

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 CHANGED
@@ -62,6 +62,8 @@ type GroupPin = {
62
62
  };
63
63
  type Net = {
64
64
  netId: NetId;
65
+ isGround?: boolean;
66
+ isPositiveVoltageSource?: boolean;
65
67
  };
66
68
  type InputProblem = {
67
69
  chipMap: Record<ChipId, Chip>;
@@ -74,8 +76,13 @@ type InputProblem = {
74
76
  chipGap: number;
75
77
  /** The minimum gap between two partitions */
76
78
  partitionGap: number;
79
+ decouplingCapsGap?: number;
77
80
  inferDecouplingCaps?: boolean;
78
81
  };
82
+ interface PartitionInputProblem extends InputProblem {
83
+ isPartition?: true;
84
+ partitionType?: "default" | "decoupling_caps";
85
+ }
79
86
 
80
87
  /**
81
88
  * Identifies decoupling capacitor groups based on specific criteria:
@@ -93,7 +100,7 @@ interface DecouplingCapGroup {
93
100
  /**
94
101
  * Identify decoupling capacitor groups based on specific criteria:
95
102
  * 1. Component has exactly 2 pins and restricted rotation (0/180 only or no rotation)
96
- * 2. One pin indirectly connected to net with "y+" restriction, one to "y-" restriction
103
+ * 2. One pin indirectly connected to net with isGround and one to isPositiveVoltageSource
97
104
  * 3. At least one pin directly connected to a chip (the main chip, typically a microcontroller)
98
105
  */
99
106
  declare class IdentifyDecouplingCapsSolver extends BaseSolver {
@@ -131,7 +138,7 @@ declare class IdentifyDecouplingCapsSolver extends BaseSolver {
131
138
 
132
139
  declare class ChipPartitionsSolver extends BaseSolver {
133
140
  inputProblem: InputProblem;
134
- partitions: InputProblem[];
141
+ partitions: PartitionInputProblem[];
135
142
  decouplingCapGroups?: DecouplingCapGroup[];
136
143
  constructor({ inputProblem, decouplingCapGroups, }: {
137
144
  inputProblem: InputProblem;
@@ -173,10 +180,14 @@ type OutputLayout = {
173
180
  */
174
181
 
175
182
  declare class SingleInnerPartitionPackingSolver extends BaseSolver {
176
- inputProblem: InputProblem;
183
+ partitionInputProblem: PartitionInputProblem;
177
184
  layout: OutputLayout | null;
178
185
  activeSubSolver: PackSolver2 | null;
179
- constructor(inputProblem: InputProblem);
186
+ pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
187
+ constructor(params: {
188
+ partitionInputProblem: PartitionInputProblem;
189
+ pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
190
+ });
180
191
  _step(): void;
181
192
  private createPackInput;
182
193
  private createLayoutFromPackingResult;
@@ -200,7 +211,12 @@ declare class PackInnerPartitionsSolver extends BaseSolver {
200
211
  completedSolvers: SingleInnerPartitionPackingSolver[];
201
212
  activeSolver: SingleInnerPartitionPackingSolver | null;
202
213
  currentPartitionIndex: number;
203
- constructor(partitions: InputProblem[]);
214
+ activeSubSolver: SingleInnerPartitionPackingSolver | null;
215
+ pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
216
+ constructor(params: {
217
+ partitions: InputProblem[];
218
+ pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
219
+ });
204
220
  _step(): void;
205
221
  visualize(): GraphicsObject;
206
222
  getConstructorParams(): [InputProblem[]];
@@ -249,6 +265,7 @@ declare class LayoutPipelineSolver extends BaseSolver {
249
265
  endTimeOfPhase: Record<string, number>;
250
266
  timeSpentOnPhase: Record<string, number>;
251
267
  firstIterationOfPhase: Record<string, number>;
268
+ pinIdToStronglyConnectedPins: Record<PinId, ChipPin[]>;
252
269
  inputProblem: InputProblem;
253
270
  chipPartitions?: ChipPartitionsSolver["partitions"];
254
271
  packedPartitions?: PackedPartition[];
@@ -284,4 +301,4 @@ declare class LayoutPipelineSolver extends BaseSolver {
284
301
  getOutputLayout(): OutputLayout;
285
302
  }
286
303
 
287
- 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 };
304
+ 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
@@ -345,11 +345,13 @@ var ChipPartitionsSolver = class extends BaseSolver {
345
345
  for (const capId of group.decouplingCapChipIds) {
346
346
  if (inputProblem.chipMap[capId]) {
347
347
  capsOnly.push(capId);
348
- decapChipIdSet.add(capId);
349
348
  }
350
349
  }
351
- if (capsOnly.length > 0) {
350
+ if (capsOnly.length >= 2) {
352
351
  decapGroupPartitions.push(capsOnly);
352
+ for (const capId of capsOnly) {
353
+ decapChipIdSet.add(capId);
354
+ }
353
355
  }
354
356
  }
355
357
  }
@@ -380,10 +382,16 @@ var ChipPartitionsSolver = class extends BaseSolver {
380
382
  }
381
383
  }
382
384
  }
383
- const allPartitions = [...decapGroupPartitions, ...nonDecapPartitions];
384
- return allPartitions.map(
385
- (partition) => this.createInputProblemFromPartition(partition, inputProblem)
386
- );
385
+ return [
386
+ ...decapGroupPartitions.map(
387
+ (partition) => this.createInputProblemFromPartition(partition, inputProblem, {
388
+ partitionType: "decoupling_caps"
389
+ })
390
+ ),
391
+ ...nonDecapPartitions.map(
392
+ (partition) => this.createInputProblemFromPartition(partition, inputProblem)
393
+ )
394
+ ];
387
395
  }
388
396
  /**
389
397
  * Finds the owner chip of a given pin
@@ -422,7 +430,7 @@ var ChipPartitionsSolver = class extends BaseSolver {
422
430
  /**
423
431
  * Creates a new InputProblem containing only the components in the given partition
424
432
  */
425
- createInputProblemFromPartition(partition, originalProblem) {
433
+ createInputProblemFromPartition(partition, originalProblem, opts) {
426
434
  const chipIds = partition;
427
435
  const relevantPinIds = /* @__PURE__ */ new Set();
428
436
  for (const chipId of chipIds) {
@@ -469,13 +477,14 @@ var ChipPartitionsSolver = class extends BaseSolver {
469
477
  }
470
478
  }
471
479
  return {
480
+ ...originalProblem,
472
481
  chipMap,
473
482
  chipPinMap,
474
483
  netMap,
475
484
  pinStrongConnMap,
476
485
  netConnMap,
477
- chipGap: originalProblem.chipGap,
478
- partitionGap: originalProblem.partitionGap
486
+ isPartition: true,
487
+ partitionType: opts?.partitionType
479
488
  };
480
489
  }
481
490
  visualize() {
@@ -624,6 +633,11 @@ var IdentifyDecouplingCapsSolver = class extends BaseSolver {
624
633
  if (!mainChipId) return;
625
634
  const netPair = this.getNormalizedNetPair(currentChip);
626
635
  if (!netPair) return;
636
+ const [n1, n2] = netPair;
637
+ const net1 = this.inputProblem.netMap[n1];
638
+ const net2 = this.inputProblem.netMap[n2];
639
+ const isDecouplingNetPair = net1?.isGround && net2?.isPositiveVoltageSource || net2?.isGround && net1?.isPositiveVoltageSource;
640
+ if (!isDecouplingNetPair) return;
627
641
  this.addToGroup(mainChipId, netPair, currentChip.chipId);
628
642
  }
629
643
  visualize() {
@@ -668,14 +682,17 @@ ${group.decouplingCapGroupId}`;
668
682
  import { PackSolver2 } from "calculate-packing";
669
683
 
670
684
  // lib/utils/networkFiltering.ts
671
- function createFilteredNetworkMapping(inputProblem) {
685
+ function createFilteredNetworkMapping(params) {
686
+ const { inputProblem, pinIdToStronglyConnectedPins } = params;
672
687
  const pinToNetworkMap = /* @__PURE__ */ new Map();
673
688
  const filteredPins = /* @__PURE__ */ new Set();
689
+ let hasStrongConnections = false;
674
690
  const strongConnectedChipSides = /* @__PURE__ */ new Map();
675
691
  for (const [connKey, connected] of Object.entries(
676
692
  inputProblem.pinStrongConnMap
677
693
  )) {
678
694
  if (!connected) continue;
695
+ hasStrongConnections = true;
679
696
  const pins = connKey.split("-");
680
697
  if (pins.length === 2 && pins[0] && pins[1]) {
681
698
  const pin1 = inputProblem.chipPinMap[pins[0]];
@@ -698,45 +715,59 @@ function createFilteredNetworkMapping(inputProblem) {
698
715
  }
699
716
  }
700
717
  }
701
- for (const [connKey, connected] of Object.entries(inputProblem.netConnMap)) {
702
- if (!connected) continue;
703
- const [pinId, netId] = connKey.split("-");
704
- if (pinId && netId) {
705
- const pin = inputProblem.chipPinMap[pinId];
706
- if (!pin) continue;
707
- const chipId = pinId.split(".")[0];
708
- let shouldIncludeInNetwork = true;
709
- for (const [
710
- strongKey,
711
- strongSides
712
- ] of strongConnectedChipSides.entries()) {
713
- const [fromChip, toChip] = strongKey.split("-");
714
- if (fromChip === chipId) {
715
- for (const [otherConnKey, otherConnected] of Object.entries(
716
- inputProblem.netConnMap
717
- )) {
718
- if (!otherConnected) continue;
719
- const [otherPinId, otherNetId] = otherConnKey.split("-");
720
- if (otherNetId === netId && otherPinId && otherPinId !== pinId) {
721
- const otherPin = inputProblem.chipPinMap[otherPinId];
722
- if (!otherPin) continue;
723
- const otherChipId = otherPinId.split(".")[0];
724
- if (otherChipId === toChip) {
725
- if (!strongSides.has(otherPin.side)) {
726
- shouldIncludeInNetwork = false;
727
- break;
718
+ if (hasStrongConnections) {
719
+ for (const [connKey, connected] of Object.entries(
720
+ inputProblem.netConnMap
721
+ )) {
722
+ if (!connected) continue;
723
+ const [pinId, netId] = connKey.split("-");
724
+ if (pinId && netId) {
725
+ filteredPins.add(pinId);
726
+ }
727
+ }
728
+ } else {
729
+ for (const [connKey, connected] of Object.entries(
730
+ inputProblem.netConnMap
731
+ )) {
732
+ if (!connected) continue;
733
+ const [pinId, netId] = connKey.split("-");
734
+ if (pinId && netId) {
735
+ const pin = inputProblem.chipPinMap[pinId];
736
+ if (!pin) continue;
737
+ const chipId = pinId.split(".")[0];
738
+ let shouldIncludeInNetwork = true;
739
+ for (const [
740
+ strongKey,
741
+ strongSides
742
+ ] of strongConnectedChipSides.entries()) {
743
+ const [fromChip, toChip] = strongKey.split("-");
744
+ if (fromChip === chipId) {
745
+ for (const [otherConnKey, otherConnected] of Object.entries(
746
+ inputProblem.netConnMap
747
+ )) {
748
+ if (!otherConnected) continue;
749
+ const [otherPinId, otherNetId] = otherConnKey.split("-");
750
+ if (otherNetId === netId && otherPinId && otherPinId !== pinId) {
751
+ const otherPin = inputProblem.chipPinMap[otherPinId];
752
+ if (!otherPin) continue;
753
+ const otherChipId = otherPinId.split(".")[0];
754
+ if (otherChipId === toChip) {
755
+ if (!strongSides.has(otherPin.side)) {
756
+ shouldIncludeInNetwork = false;
757
+ break;
758
+ }
728
759
  }
729
760
  }
730
761
  }
731
762
  }
732
763
  }
733
- }
734
- if (shouldIncludeInNetwork) {
735
- pinToNetworkMap.set(pinId, netId);
736
- } else {
737
- const disconnectedNetworkId = `${pinId}_opposite-strong-side-disconnected`;
738
- pinToNetworkMap.set(pinId, disconnectedNetworkId);
739
- filteredPins.add(pinId);
764
+ if (shouldIncludeInNetwork) {
765
+ pinToNetworkMap.set(pinId, netId);
766
+ } else {
767
+ const disconnectedNetworkId = `${pinId}_opposite-strong-side-disconnected`;
768
+ pinToNetworkMap.set(pinId, disconnectedNetworkId);
769
+ filteredPins.add(pinId);
770
+ }
740
771
  }
741
772
  }
742
773
  }
@@ -782,11 +813,13 @@ var getPadsBoundingBox = (pads) => {
782
813
  // lib/solvers/PackInnerPartitionsSolver/SingleInnerPartitionPackingSolver.ts
783
814
  var PIN_SIZE = 0.1;
784
815
  var SingleInnerPartitionPackingSolver = class extends BaseSolver {
785
- inputProblem;
816
+ partitionInputProblem;
786
817
  layout = null;
787
- constructor(inputProblem) {
818
+ pinIdToStronglyConnectedPins;
819
+ constructor(params) {
788
820
  super();
789
- this.inputProblem = inputProblem;
821
+ this.partitionInputProblem = params.partitionInputProblem;
822
+ this.pinIdToStronglyConnectedPins = params.pinIdToStronglyConnectedPins;
790
823
  }
791
824
  _step() {
792
825
  if (!this.activeSubSolver) {
@@ -809,53 +842,55 @@ var SingleInnerPartitionPackingSolver = class extends BaseSolver {
809
842
  }
810
843
  }
811
844
  createPackInput() {
812
- const { pinToNetworkMap } = createFilteredNetworkMapping(this.inputProblem);
813
- const packComponents = Object.entries(this.inputProblem.chipMap).map(
814
- ([chipId, chip]) => {
815
- const pads = [];
816
- for (const pinId of chip.pins) {
817
- const pin = this.inputProblem.chipPinMap[pinId];
818
- if (!pin) continue;
819
- const networkId = pinToNetworkMap.get(pinId) || `${pinId}_isolated`;
820
- pads.push({
821
- padId: pinId,
822
- networkId,
823
- type: "rect",
824
- offset: { x: pin.offset.x, y: pin.offset.y },
825
- size: { x: PIN_SIZE, y: PIN_SIZE }
826
- // Small size for pins
827
- });
828
- }
829
- const padsBoundingBox = getPadsBoundingBox(pads);
830
- const padsBoundingBoxSize = {
831
- x: padsBoundingBox.maxX - padsBoundingBox.minX,
832
- y: padsBoundingBox.maxY - padsBoundingBox.minY
833
- };
845
+ const pinToNetworkMap = createFilteredNetworkMapping({
846
+ inputProblem: this.partitionInputProblem,
847
+ pinIdToStronglyConnectedPins: this.pinIdToStronglyConnectedPins
848
+ }).pinToNetworkMap;
849
+ const packComponents = Object.entries(
850
+ this.partitionInputProblem.chipMap
851
+ ).map(([chipId, chip]) => {
852
+ const pads = [];
853
+ for (const pinId of chip.pins) {
854
+ const pin = this.partitionInputProblem.chipPinMap[pinId];
855
+ if (!pin) continue;
856
+ const networkId = pinToNetworkMap.get(pinId) || `${pinId}_isolated`;
834
857
  pads.push({
835
- padId: `${chipId}_body`,
836
- networkId: `${chipId}_body_disconnected`,
858
+ padId: pinId,
859
+ networkId,
837
860
  type: "rect",
838
- offset: { x: 0, y: 0 },
839
- size: {
840
- x: Math.max(padsBoundingBoxSize.x, chip.size.x),
841
- y: Math.max(padsBoundingBoxSize.y, chip.size.y)
842
- }
861
+ offset: { x: pin.offset.x, y: pin.offset.y },
862
+ size: { x: PIN_SIZE, y: PIN_SIZE }
863
+ // Small size for pins
843
864
  });
844
- return {
845
- componentId: chipId,
846
- pads,
847
- availableRotationDegrees: chip.availableRotations || [
848
- 0,
849
- 90,
850
- 180,
851
- 270
852
- ]
853
- };
854
865
  }
855
- );
866
+ const padsBoundingBox = getPadsBoundingBox(pads);
867
+ const padsBoundingBoxSize = {
868
+ x: padsBoundingBox.maxX - padsBoundingBox.minX,
869
+ y: padsBoundingBox.maxY - padsBoundingBox.minY
870
+ };
871
+ pads.push({
872
+ padId: `${chipId}_body`,
873
+ networkId: `${chipId}_body_disconnected`,
874
+ type: "rect",
875
+ offset: { x: 0, y: 0 },
876
+ size: {
877
+ x: Math.max(padsBoundingBoxSize.x, chip.size.x),
878
+ y: Math.max(padsBoundingBoxSize.y, chip.size.y)
879
+ }
880
+ });
881
+ return {
882
+ componentId: chipId,
883
+ pads,
884
+ availableRotationDegrees: chip.availableRotations || [0, 90, 180, 270]
885
+ };
886
+ });
887
+ let minGap = this.partitionInputProblem.chipGap;
888
+ if (this.partitionInputProblem.partitionType === "decoupling_caps") {
889
+ minGap = this.partitionInputProblem.decouplingCapsGap ?? minGap;
890
+ }
856
891
  return {
857
892
  components: packComponents,
858
- minGap: this.inputProblem.chipGap,
893
+ minGap,
859
894
  packOrderStrategy: "largest_to_smallest",
860
895
  packPlacementStrategy: "minimum_closest_sum_squared_distance"
861
896
  };
@@ -880,13 +915,13 @@ var SingleInnerPartitionPackingSolver = class extends BaseSolver {
880
915
  return this.activeSubSolver.visualize();
881
916
  }
882
917
  if (!this.layout) {
883
- const basicLayout = doBasicInputProblemLayout(this.inputProblem);
884
- return visualizeInputProblem(this.inputProblem, basicLayout);
918
+ const basicLayout = doBasicInputProblemLayout(this.partitionInputProblem);
919
+ return visualizeInputProblem(this.partitionInputProblem, basicLayout);
885
920
  }
886
- return visualizeInputProblem(this.inputProblem, this.layout);
921
+ return visualizeInputProblem(this.partitionInputProblem, this.layout);
887
922
  }
888
923
  getConstructorParams() {
889
- return [this.inputProblem];
924
+ return [this.partitionInputProblem];
890
925
  }
891
926
  };
892
927
 
@@ -898,9 +933,11 @@ var PackInnerPartitionsSolver = class extends BaseSolver {
898
933
  completedSolvers = [];
899
934
  activeSolver = null;
900
935
  currentPartitionIndex = 0;
901
- constructor(partitions) {
936
+ pinIdToStronglyConnectedPins;
937
+ constructor(params) {
902
938
  super();
903
- this.partitions = partitions;
939
+ this.partitions = params.partitions;
940
+ this.pinIdToStronglyConnectedPins = params.pinIdToStronglyConnectedPins;
904
941
  }
905
942
  _step() {
906
943
  if (this.currentPartitionIndex >= this.partitions.length) {
@@ -909,9 +946,10 @@ var PackInnerPartitionsSolver = class extends BaseSolver {
909
946
  }
910
947
  if (!this.activeSolver) {
911
948
  const currentPartition = this.partitions[this.currentPartitionIndex];
912
- this.activeSolver = new SingleInnerPartitionPackingSolver(
913
- currentPartition
914
- );
949
+ this.activeSolver = new SingleInnerPartitionPackingSolver({
950
+ partitionInputProblem: currentPartition,
951
+ pinIdToStronglyConnectedPins: this.pinIdToStronglyConnectedPins
952
+ });
915
953
  this.activeSubSolver = this.activeSolver;
916
954
  }
917
955
  this.activeSolver.step();
@@ -1225,6 +1263,29 @@ var PartitionPackingSolver = class extends BaseSolver {
1225
1263
  }
1226
1264
  };
1227
1265
 
1266
+ // lib/solvers/LayoutPipelineSolver/getPinIdToStronglyConnectedPinsObj.ts
1267
+ var getPinIdToStronglyConnectedPinsObj = (inputProblem) => {
1268
+ const pinIdToStronglyConnectedPins = {};
1269
+ const pinIds = Object.keys(inputProblem.chipPinMap);
1270
+ for (let i = 0; i < pinIds.length; i++) {
1271
+ for (let j = i + 1; j < pinIds.length; j++) {
1272
+ const pinId1 = pinIds[i];
1273
+ const pinId2 = pinIds[j];
1274
+ if (inputProblem.pinStrongConnMap[`${pinId1}-${pinId2}`] || inputProblem.pinStrongConnMap[`${pinId2}-${pinId1}`]) {
1275
+ pinIdToStronglyConnectedPins[pinId1] ??= [];
1276
+ pinIdToStronglyConnectedPins[pinId2] ??= [];
1277
+ pinIdToStronglyConnectedPins[pinId1].push(
1278
+ inputProblem.chipPinMap[pinId2]
1279
+ );
1280
+ pinIdToStronglyConnectedPins[pinId2].push(
1281
+ inputProblem.chipPinMap[pinId1]
1282
+ );
1283
+ }
1284
+ }
1285
+ }
1286
+ return pinIdToStronglyConnectedPins;
1287
+ };
1288
+
1228
1289
  // lib/solvers/LayoutPipelineSolver/LayoutPipelineSolver.ts
1229
1290
  function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
1230
1291
  return {
@@ -1243,6 +1304,8 @@ var LayoutPipelineSolver = class extends BaseSolver {
1243
1304
  endTimeOfPhase;
1244
1305
  timeSpentOnPhase;
1245
1306
  firstIterationOfPhase;
1307
+ // Computed utility objects
1308
+ pinIdToStronglyConnectedPins;
1246
1309
  inputProblem;
1247
1310
  chipPartitions;
1248
1311
  packedPartitions;
@@ -1274,7 +1337,12 @@ var LayoutPipelineSolver = class extends BaseSolver {
1274
1337
  definePipelineStep(
1275
1338
  "packInnerPartitionsSolver",
1276
1339
  PackInnerPartitionsSolver,
1277
- () => [this.chipPartitions || [this.inputProblem]],
1340
+ () => [
1341
+ {
1342
+ partitions: this.chipPartitions,
1343
+ pinIdToStronglyConnectedPins: this.pinIdToStronglyConnectedPins
1344
+ }
1345
+ ],
1278
1346
  {
1279
1347
  onSolved: (_solver) => {
1280
1348
  this.packedPartitions = this.packInnerPartitionsSolver.packedPartitions;
@@ -1304,6 +1372,7 @@ var LayoutPipelineSolver = class extends BaseSolver {
1304
1372
  this.endTimeOfPhase = {};
1305
1373
  this.timeSpentOnPhase = {};
1306
1374
  this.firstIterationOfPhase = {};
1375
+ this.pinIdToStronglyConnectedPins = getPinIdToStronglyConnectedPinsObj(inputProblem);
1307
1376
  }
1308
1377
  currentPipelineStepIndex = 0;
1309
1378
  _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.14",
5
+ "version": "0.0.16",
6
6
  "files": [
7
7
  "dist"
8
8
  ],