Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { doBasicInputProblemLayout } from "../LayoutPipelineSolver/doBasicInputP

const PIN_SIZE = 0.1

const naturalChipIdCollator = new Intl.Collator(undefined, { numeric: true })

export class SingleInnerPartitionPackingSolver extends BaseSolver {
partitionInputProblem: PartitionInputProblem
layout: OutputLayout | null = null
Expand All @@ -38,6 +40,13 @@ export class SingleInnerPartitionPackingSolver extends BaseSolver {
}

override _step() {
if (this.partitionInputProblem.partitionType === "decoupling_caps") {
this.layout = this.createDecouplingCapsRowLayout()
this.solved = true
this.activeSubSolver = null
return
}

// Initialize PackSolver2 if not already created
if (!this.activeSubSolver) {
const packInput = this.createPackInput()
Expand All @@ -64,6 +73,47 @@ export class SingleInnerPartitionPackingSolver extends BaseSolver {
}
}

private createDecouplingCapsRowLayout(): OutputLayout {
const chips = Object.values(this.partitionInputProblem.chipMap).sort(
(a, b) => naturalChipIdCollator.compare(a.chipId, b.chipId),
)
const gap =
this.partitionInputProblem.decouplingCapsGap ??
this.partitionInputProblem.chipGap

const rowItems = chips.map((chip) => {
const rotation = chip.availableRotations?.includes(0)
? 0
: (chip.availableRotations?.[0] ?? 0)
const rotationSwapsSize = rotation === 90 || rotation === 270
return {
chip,
rotation,
width: rotationSwapsSize ? chip.size.y : chip.size.x,
}
})

const totalWidth =
rowItems.reduce((sum, item) => sum + item.width, 0) +
Math.max(0, rowItems.length - 1) * gap
let cursorX = -totalWidth / 2
const chipPlacements: Record<string, Placement> = {}

for (const item of rowItems) {
chipPlacements[item.chip.chipId] = {
x: cursorX + item.width / 2,
y: 0,
ccwRotationDegrees: item.rotation,
}
cursorX += item.width + gap
}

return {
chipPlacements,
groupPlacements: {},
}
}

private createPackInput(): PackInput {
// Fall back to filtered mapping (weak + strong)
const pinToNetworkMap = createFilteredNetworkMapping({
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@types/bun": "latest",
"bpc-graph": "^0.0.66",
"calculate-packing": "^0.0.31",
"circuit-to-svg": "^0.0.345",
"circuit-json": "^0.0.226",
"graphics-debug": "^0.0.64",
"react-cosmos": "^7.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { expect, test } from "bun:test"
import { SingleInnerPartitionPackingSolver } from "../../lib/solvers/PackInnerPartitionsSolver/SingleInnerPartitionPackingSolver"
import type { PartitionInputProblem } from "../../lib/types/InputProblem"

const makeDecouplingPartition = (
overrides: Partial<PartitionInputProblem> = {},
): PartitionInputProblem => ({
chipMap: {
C10: {
chipId: "C10",
pins: [],
size: { x: 1, y: 0.5 },
availableRotations: [0, 180],
},
C2: {
chipId: "C2",
pins: [],
size: { x: 2, y: 0.5 },
availableRotations: [0, 180],
},
C1: {
chipId: "C1",
pins: [],
size: { x: 1, y: 0.5 },
availableRotations: [0, 180],
},
},
chipPinMap: {},
netMap: {},
pinStrongConnMap: {},
netConnMap: {},
chipGap: 0.5,
partitionGap: 2,
decouplingCapsGap: 0.25,
isPartition: true,
partitionType: "decoupling_caps",
...overrides,
})

test("SingleInnerPartitionPackingSolver places decoupling caps in a centered natural-id row", () => {
const solver = new SingleInnerPartitionPackingSolver({
partitionInputProblem: makeDecouplingPartition(),
pinIdToStronglyConnectedPins: {},
})

solver.step()

expect(solver.solved).toBe(true)
expect(solver.failed).toBe(false)
expect(solver.activeSubSolver).toBeNull()
expect(solver.layout?.chipPlacements).toEqual({
C1: { x: -1.75, y: 0, ccwRotationDegrees: 0 },
C2: { x: 0, y: 0, ccwRotationDegrees: 0 },
C10: { x: 1.75, y: 0, ccwRotationDegrees: 0 },
})
})

test("SingleInnerPartitionPackingSolver falls back to chipGap for decoupling cap row spacing", () => {
const solver = new SingleInnerPartitionPackingSolver({
partitionInputProblem: makeDecouplingPartition({
decouplingCapsGap: undefined,
}),
pinIdToStronglyConnectedPins: {},
})

solver.step()

expect(solver.solved).toBe(true)
expect(solver.layout?.chipPlacements.C1?.x).toBe(-2)
expect(solver.layout?.chipPlacements.C2?.x).toBe(0)
expect(solver.layout?.chipPlacements.C10?.x).toBe(2)
})
Loading