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
10 changes: 9 additions & 1 deletion lib/data-structures/ChipObstacleSpatialIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface SpatiallyIndexedChip extends InputChip {

export class ChipObstacleSpatialIndex {
chips: Array<SpatiallyIndexedChip>
spatialIndex: Flatbush
spatialIndex: Flatbush | null
spatialIndexIdToChip: Map<number, SpatiallyIndexedChip>

constructor(chips: InputChip[]) {
Expand All @@ -21,6 +21,13 @@ export class ChipObstacleSpatialIndex {
}))

this.spatialIndexIdToChip = new Map()

if (chips.length === 0) {
// Flatbush requires at least 1 item; skip index construction for empty input
this.spatialIndex = null
return
}

this.spatialIndex = new Flatbush(chips.length)

for (const chip of this.chips) {
Expand All @@ -37,6 +44,7 @@ export class ChipObstacleSpatialIndex {
}

getChipsInBounds(bounds: Bounds): Array<InputChip & { bounds: Bounds }> {
if (!this.spatialIndex) return []
const chipSpatialIndexIds = this.spatialIndex.search(
bounds.minX,
bounds.minY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
this.pinMap = getPinMap(params.inputProblem)
this.chipObstacleSpatialIndex =
params.inputProblem._chipObstacleSpatialIndex ??
new ChipObstacleSpatialIndex(params.inputProblem.chips)
new ChipObstacleSpatialIndex(params.inputProblem.chips ?? [])
this.maxSearchDistance = getMaxSearchDistance(params.inputProblem)
this.queuedLabelIndices = this.getProcessableLabelIndices()
this.setCurrentLabel(this.queuedLabelIndices[0] ?? null)
Expand Down Expand Up @@ -290,7 +290,10 @@ export class AvailableNetOrientationSolver extends BaseSolver {

private getAvailableOrientations(label: NetLabelPlacement) {
const effectiveNetId = label.netId ?? label.globalConnNetId
return this.inputProblem.availableNetLabelOrientations[effectiveNetId] ?? []
return (
(this.inputProblem.availableNetLabelOrientations ?? {})[effectiveNetId] ??
[]
)
}

private findValidShiftedCandidate(
Expand Down Expand Up @@ -627,36 +630,36 @@ export class AvailableNetOrientationSolver extends BaseSolver {

private getNetLabelWidth(label: NetLabelPlacement) {
if (label.netId) {
const ncWidth = this.inputProblem.netConnections.find(
const ncWidth = (this.inputProblem.netConnections ?? []).find(
(connection) => connection.netId === label.netId,
)?.netLabelWidth
if (ncWidth !== undefined) return ncWidth

const dcWidthByNetId = this.inputProblem.directConnections.find(
const dcWidthByNetId = (this.inputProblem.directConnections ?? []).find(
(dc) => dc.netId === label.netId,
)?.netLabelWidth
if (dcWidthByNetId !== undefined) return dcWidthByNetId
}

const dcWidthByPinId = this.inputProblem.directConnections.find((dc) =>
dc.pinIds.some((pid) => label.pinIds.includes(pid)),
const dcWidthByPinId = (this.inputProblem.directConnections ?? []).find(
(dc) => dc.pinIds.some((pid) => label.pinIds.includes(pid)),
)?.netLabelWidth
if (dcWidthByPinId !== undefined) return dcWidthByPinId

return this.inputProblem.netConnections.find((nc) =>
return (this.inputProblem.netConnections ?? []).find((nc) =>
nc.pinIds.some((pid) => label.pinIds.includes(pid)),
)?.netLabelWidth
}

private getNetLabelHeight(label: NetLabelPlacement) {
if (label.netId) {
const ncHeight = this.inputProblem.netConnections.find(
const ncHeight = (this.inputProblem.netConnections ?? []).find(
(connection) => connection.netId === label.netId,
)?.netLabelHeight
if (ncHeight !== undefined) return ncHeight
}

return this.inputProblem.netConnections.find((nc) =>
return (this.inputProblem.netConnections ?? []).find((nc) =>
nc.pinIds.some((pid) => label.pinIds.includes(pid)),
)?.netLabelHeight
}
Expand Down
2 changes: 1 addition & 1 deletion lib/solvers/AvailableNetOrientationSolver/geometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ const sameY = (a: Point, b: Point) => Math.abs(a.y - b.y) <= EPS

export const getMaxSearchDistance = (inputProblem: InputProblem) => {
const maxChipWidth = Math.max(
...inputProblem.chips.map((chip) => chip.width),
...(inputProblem.chips ?? []).map((chip) => chip.width),
1,
)
return maxChipWidth * 3
Expand Down
2 changes: 1 addition & 1 deletion lib/solvers/AvailableNetOrientationSolver/traces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { CandidateLabel } from "./types"

export const getPinMap = (inputProblem: InputProblem) => {
const pinMap: Record<string, InputPin & { chipId: string }> = {}
for (const chip of inputProblem.chips) {
for (const chip of inputProblem.chips ?? []) {
for (const pin of chip.pins) {
pinMap[pin.pinId] = { ...pin, chipId: chip.chipId }
}
Expand Down
2 changes: 1 addition & 1 deletion lib/solvers/Example28Solver/Example28Solver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class Example28Solver extends BaseSolver {
private hasExplicitOrientationConstraint(label: NetLabelPlacement) {
const effectiveNetId = label.netId ?? label.globalConnNetId
return Object.hasOwn(
this.inputProblem.availableNetLabelOrientations,
this.inputProblem.availableNetLabelOrientations ?? {},
effectiveNetId,
)
}
Expand Down
2 changes: 1 addition & 1 deletion lib/solvers/GuidelinesSolver/GuidelinesSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class GuidelinesSolver extends BaseSolver {
},
]
this.chipPairsGenerator = getGeneratorForAllChipPairs(
this.inputProblem.chips,
this.inputProblem.chips ?? [],
)

this.usedXGuidelines = new Set()
Expand Down
2 changes: 1 addition & 1 deletion lib/solvers/GuidelinesSolver/getInputProblemBounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const getInputProblemBounds = (inputProblem: InputProblem) => {
minY: Infinity,
maxY: -Infinity,
}
for (const chip of inputProblem.chips) {
for (const chip of inputProblem.chips ?? []) {
const chipBounds = getInputChipBounds(chip)
bounds.minX = Math.min(bounds.minX, chipBounds.minX)
bounds.maxX = Math.max(bounds.maxX, chipBounds.maxX)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class LongDistancePairSolver extends BaseSolver {
const { netConnMap } = getConnectivityMapsFromInputProblem(inputProblem)
this.netConnMap = netConnMap
const pinMap = new Map<PinId, InputPin & { chipId: string }>()
for (const chip of inputProblem.chips) {
for (const chip of inputProblem.chips ?? []) {
this.chipMap[chip.chipId] = chip
for (const pin of chip.pins) {
pinMap.set(pin.pinId, { ...pin, chipId: chip.chipId })
Expand Down
10 changes: 6 additions & 4 deletions lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,27 +49,29 @@ export class MspConnectionPairSolver extends BaseSolver {
this.globalConnMap = netConnMap

this.pinMap = {}
for (const chip of inputProblem.chips) {
for (const chip of inputProblem.chips ?? []) {
for (const pin of chip.pins) {
this.pinMap[pin.pinId] = { ...pin, chipId: chip.chipId }
}
}

this.chipMap = {}
for (const chip of inputProblem.chips) {
for (const chip of inputProblem.chips ?? []) {
this.chipMap[chip.chipId] = chip
}

// Build a mapping from PinId to user-provided netId (if any)
this.userNetIdByPinId = {}
for (const dc of inputProblem.directConnections) {
for (const dc of inputProblem.directConnections ?? []) {
if (!dc) continue
if (dc.netId) {
const [a, b] = dc.pinIds
this.userNetIdByPinId[a] = dc.netId
this.userNetIdByPinId[b] = dc.netId
}
}
for (const nc of inputProblem.netConnections) {
for (const nc of inputProblem.netConnections ?? []) {
if (!nc) continue
for (const pid of nc.pinIds) {
this.userNetIdByPinId[pid] = nc.netId
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ export const getConnectivityMapsFromInputProblem = (
): { directConnMap: ConnectivityMap; netConnMap: ConnectivityMap } => {
const directConnMap = new ConnectivityMap({})

for (const directConn of inputProblem.directConnections) {
for (const directConn of inputProblem.directConnections ?? []) {
if (!directConn) continue
directConnMap.addConnections([
directConn.netId
? [directConn.netId, ...directConn.pinIds]
Expand All @@ -16,7 +17,8 @@ export const getConnectivityMapsFromInputProblem = (

const netConnMap = new ConnectivityMap(directConnMap.netMap)

for (const netConn of inputProblem.netConnections) {
for (const netConn of inputProblem.netConnections ?? []) {
if (!netConn) continue
netConnMap.addConnections([[netConn.netId, ...netConn.pinIds]])
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export class NetLabelNetLabelCollisionSolver extends BaseSolver {
this.outputNetLabelPlacements = [...params.netLabelPlacements]
this.chipIndex =
params.inputProblem._chipObstacleSpatialIndex ??
new ChipObstacleSpatialIndex(params.inputProblem.chips)
new ChipObstacleSpatialIndex(params.inputProblem.chips ?? [])
this.traceMap = Object.fromEntries(
params.traces.map((t) => [t.mspPairId, t]),
) as Record<MspConnectionPairId, SolvedTracePath>
Expand Down
27 changes: 13 additions & 14 deletions lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,30 +109,30 @@ export class NetLabelPlacementSolver extends BaseSolver {
)

const pinIdToPinMap = new Map<string, unknown>()
for (const chip of this.inputProblem.chips) {
for (const chip of this.inputProblem.chips ?? []) {
for (const pin of chip.pins) {
pinIdToPinMap.set(pin.pinId, pin)
}
}

// Map pins to user-provided netIds (if any)
const userNetIdByPinId: Record<string, string | undefined> = {}
for (const dc of this.inputProblem.directConnections) {
for (const dc of this.inputProblem.directConnections ?? []) {
if (dc.netId) {
const [a, b] = dc.pinIds
userNetIdByPinId[a] = dc.netId
userNetIdByPinId[b] = dc.netId
}
}
for (const nc of this.inputProblem.netConnections) {
for (const nc of this.inputProblem.netConnections ?? []) {
for (const pid of nc.pinIds) {
userNetIdByPinId[pid] = nc.netId
}
}

const groups: Array<OverlappingSameNetTraceGroup> = []

const allPinIds = this.inputProblem.chips.flatMap((c) =>
const allPinIds = (this.inputProblem.chips ?? []).flatMap((c) =>
c.pins.map((p) => p.pinId),
)

Expand Down Expand Up @@ -255,12 +255,12 @@ export class NetLabelPlacementSolver extends BaseSolver {
group: OverlappingSameNetTraceGroup,
): number | undefined {
if (group.netId) {
const ncWidth = this.inputProblem.netConnections.find(
const ncWidth = (this.inputProblem.netConnections ?? []).find(
(nc) => nc.netId === group.netId,
)?.netLabelWidth
if (ncWidth !== undefined) return ncWidth

const dcWidthByNetId = this.inputProblem.directConnections.find(
const dcWidthByNetId = (this.inputProblem.directConnections ?? []).find(
(dc) => dc.netId === group.netId,
)?.netLabelWidth
if (dcWidthByNetId !== undefined) return dcWidthByNetId
Expand All @@ -271,12 +271,12 @@ export class NetLabelPlacementSolver extends BaseSolver {
pinIds.push(group.portOnlyPinId)
}

const dcWidthByPinId = this.inputProblem.directConnections.find((dc) =>
dc.pinIds.some((pid) => pinIds.includes(pid)),
const dcWidthByPinId = (this.inputProblem.directConnections ?? []).find(
(dc) => dc.pinIds.some((pid) => pinIds.includes(pid)),
)?.netLabelWidth
if (dcWidthByPinId !== undefined) return dcWidthByPinId

return this.inputProblem.netConnections.find((nc) =>
return (this.inputProblem.netConnections ?? []).find((nc) =>
nc.pinIds.some((pid) => pinIds.includes(pid)),
)?.netLabelWidth
}
Expand All @@ -285,7 +285,7 @@ export class NetLabelPlacementSolver extends BaseSolver {
group: OverlappingSameNetTraceGroup,
): number | undefined {
if (group.netId) {
const ncHeight = this.inputProblem.netConnections.find(
const ncHeight = (this.inputProblem.netConnections ?? []).find(
(nc) => nc.netId === group.netId,
)?.netLabelHeight
if (ncHeight !== undefined) return ncHeight
Expand All @@ -296,7 +296,7 @@ export class NetLabelPlacementSolver extends BaseSolver {
pinIds.push(group.portOnlyPinId)
}

return this.inputProblem.netConnections.find((nc) =>
return (this.inputProblem.netConnections ?? []).find((nc) =>
nc.pinIds.some((pid) => pinIds.includes(pid)),
)?.netLabelHeight
}
Expand Down Expand Up @@ -374,9 +374,8 @@ export class NetLabelPlacementSolver extends BaseSolver {
inputProblem: this.inputProblem,
inputTraceMap: this.inputTraceMap,
overlappingSameNetTraceGroup: nextOverlappingSameNetTraceGroup,
availableOrientations: this.inputProblem.availableNetLabelOrientations[
netId
] ?? ["x+", "x-", "y+", "y-"],
availableOrientations: (this.inputProblem.availableNetLabelOrientations ??
{})[netId] ?? ["x+", "x-", "y+", "y-"],
netLabelWidth,
netLabelHeight,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export class SingleNetLabelPlacementSolver extends BaseSolver {

this.chipObstacleSpatialIndex =
params.inputProblem._chipObstacleSpatialIndex ??
new ChipObstacleSpatialIndex(params.inputProblem.chips)
new ChipObstacleSpatialIndex(params.inputProblem.chips ?? [])
}

override getConstructorParams(): ConstructorParameters<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function chooseHostTraceForGroup(params: {
mspConnectionPairIds,
} = params
const chipsById: Record<string, InputChip> = Object.fromEntries(
inputProblem.chips.map((c) => [c.chipId, c]),
(inputProblem.chips ?? []).map((c) => [c.chipId, c]),
)

let groupTraces = Object.values(inputTraceMap).filter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function solveNetLabelPlacementForPortOnlyPin(params: {
// Find pin coordinates and facing direction
let pin: { x: number; y: number } | null = null
let pinFacingDirection: FacingDirection | null = null
for (const chip of inputProblem.chips) {
for (const chip of inputProblem.chips ?? []) {
const p = chip.pins.find((pp) => pp.pinId === pinId)
if (p) {
pin = { x: p.x, y: p.y }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export class RailNetLabelCornerPlacementSolver extends BaseSolver {
}

private intersectsAnyChip(bounds: Bounds) {
return this.inputProblem.chips.some((chip) =>
return (this.inputProblem.chips ?? []).some((chip) =>
rectsOverlap(bounds, getRectBounds(chip.center, chip.width, chip.height)),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ export class SchematicTraceSingleLineSolver extends BaseSolver {
this.chipMap = params.chipMap
this.chipObstacleSpatialIndex =
this.inputProblem._chipObstacleSpatialIndex ||
new ChipObstacleSpatialIndex(this.inputProblem.chips)
new ChipObstacleSpatialIndex(this.inputProblem.chips ?? [])

if (!this.inputProblem._chipObstacleSpatialIndex) {
this.inputProblem._chipObstacleSpatialIndex =
this.chipObstacleSpatialIndex
}

// Build a lookup of all pins by id and attach chipId to each pin entry
for (const chip of this.inputProblem.chips) {
for (const chip of this.inputProblem.chips ?? []) {
for (const pin of chip.pins) {
this.pinIdMap.set(pin.pinId, { ...pin, chipId: chip.chipId })
}
Expand Down
Loading
Loading