Skip to content
Draft
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
9 changes: 9 additions & 0 deletions lib/DuplicateCongestedPortSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@ const createSingleRouteProblem = (
problem.portPenalty === undefined
? undefined
: new Float64Array(problem.portPenalty),
portalLayerRefinementLockedRouteMask:
problem.portalLayerRefinementLockedRouteMask === undefined
? undefined
: Int8Array.from([
problem.portalLayerRefinementLockedRouteMask[routeId] ?? 0,
]),
})

const getUsedPortIdsForSolvedRoute = (
Expand Down Expand Up @@ -432,6 +438,9 @@ export class DuplicateCongestedPortSolver extends BaseSolver {
duplicatedPortData.duplicatePortUseCount = useCount
duplicatedPortData.duplicatePortProximity = duplicatePortProximity
duplicatedPortData.repairReason = "congested-port"
if (typeof duplicatedPortData.physicalPortGroupId === "string") {
duplicatedPortData.physicalPortGroupId = `${duplicatedPortData.physicalPortGroupId}::source-${sourcePortId}::duplicate-${duplicateIndex}`
}

ports.push({
...sourcePort,
Expand Down
6 changes: 5 additions & 1 deletion lib/compat/convertToSerializedHyperGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,13 +299,17 @@ const getSerializedConnection = (
? routeMetadata.mutuallyConnectedNetworkId
: undefined

const portalLayerRefinementLocked =
solver.problem.portalLayerRefinementLockedRouteMask?.[routeId] === 1

return {
connectionId: metadataConnectionId,
startRegionId: metadataStartRegionId ?? startRegionId,
endRegionId: metadataEndRegionId ?? endRegionId,
mutuallyConnectedNetworkId:
metadataNetworkId ?? `net-${solver.problem.routeNet[routeId]}`,
}
...(portalLayerRefinementLocked && { portalLayerRefinementLocked: true }),
} as SerializedConnection
}

const getSerializedSolvedRoute = (
Expand Down
96 changes: 96 additions & 0 deletions lib/compat/loadSerializedHyperGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,27 @@ const getSerializedPortY = (
port: SerializedHyperGraph["ports"][number],
): number => Number(port.d?.y ?? 0)

const getSerializedPhysicalPortGroupId = (
port: SerializedHyperGraph["ports"][number],
): string | undefined => {
const physicalPortGroupId = port.d?.physicalPortGroupId
return typeof physicalPortGroupId === "string" &&
physicalPortGroupId.length > 0
? physicalPortGroupId
: undefined
}

const getConnectionPortalLayerRefinementLock = (
connection: NonNullable<SerializedHyperGraph["connections"]>[number],
): boolean | undefined => {
const value = (
connection as typeof connection & {
portalLayerRefinementLocked?: unknown
}
).portalLayerRefinementLocked
return typeof value === "boolean" ? value : undefined
}

const computePortAngle = (
port: SerializedHyperGraph["ports"][number],
region: SerializedHyperGraph["regions"][number] | undefined,
Expand Down Expand Up @@ -390,6 +411,27 @@ export const loadSerializedHyperGraph = (
const portX = new Float64Array(portCount)
const portY = new Float64Array(portCount)
const portZ = new Int32Array(portCount)
const physicalGroupIds = [
...new Set(
filteredHyperGraph.ports
.map(getSerializedPhysicalPortGroupId)
.filter((groupId): groupId is string => groupId !== undefined),
),
].sort()
const physicalGroupIdToIndex = new Map(
physicalGroupIds.map((groupId, groupIndex) => [groupId, groupIndex]),
)
const portPhysicalGroupId = new Int32Array(portCount).fill(-1)
const physicalGroupLayerCount = Math.max(
1,
...filteredHyperGraph.ports.map((port) => getSerializedPortZ(port) + 1),
)
const physicalGroupPortIdByZ = new Int32Array(
physicalGroupIds.length * physicalGroupLayerCount,
).fill(-1)
const physicalGroupX = new Float64Array(physicalGroupIds.length)
const physicalGroupY = new Float64Array(physicalGroupIds.length)
const physicalGroupHasCoordinates = new Int8Array(physicalGroupIds.length)

filteredHyperGraph.ports.forEach((port, portIndex) => {
const region1Index = regionIdToIndex.get(port.region1Id)
Expand All @@ -405,6 +447,40 @@ export const loadSerializedHyperGraph = (
portX[portIndex] = getSerializedPortX(port)
portY[portIndex] = getSerializedPortY(port)
portZ[portIndex] = getSerializedPortZ(port)
const serializedPhysicalGroupId = getSerializedPhysicalPortGroupId(port)
if (serializedPhysicalGroupId !== undefined) {
const physicalGroupId = physicalGroupIdToIndex.get(
serializedPhysicalGroupId,
)
if (physicalGroupId === undefined) {
throw new Error(
`Port "${port.portId}" references an unknown physical portal group`,
)
}
const lookupIndex =
physicalGroupId * physicalGroupLayerCount + portZ[portIndex]
if (physicalGroupPortIdByZ[lookupIndex] !== -1) {
throw new Error(
`Physical portal group "${serializedPhysicalGroupId}" has multiple z${portZ[portIndex]} copies`,
)
}
if (physicalGroupHasCoordinates[physicalGroupId] === 1) {
if (
Math.abs(physicalGroupX[physicalGroupId] - portX[portIndex]) > 1e-9 ||
Math.abs(physicalGroupY[physicalGroupId] - portY[portIndex]) > 1e-9
) {
throw new Error(
`Physical portal group "${serializedPhysicalGroupId}" contains different XY positions`,
)
}
} else {
physicalGroupX[physicalGroupId] = portX[portIndex]
physicalGroupY[physicalGroupId] = portY[portIndex]
physicalGroupHasCoordinates[physicalGroupId] = 1
}
portPhysicalGroupId[portIndex] = physicalGroupId
physicalGroupPortIdByZ[lookupIndex] = portIndex
}
portAngleForRegion1[portIndex] = computePortAngle(
port,
filteredHyperGraph.regions[region1Index],
Expand Down Expand Up @@ -561,6 +637,10 @@ export const loadSerializedHyperGraph = (
portX,
portY,
portZ,
portPhysicalGroupId,
physicalPortalGroupCount: physicalGroupIds.length,
physicalGroupPortIdByZ,
physicalGroupLayerCount,
portMetadata,
}

Expand Down Expand Up @@ -597,6 +677,21 @@ export const loadSerializedHyperGraph = (
}
}),
)
const initiallyAssignedRouteIds = new Set(
initialAssignments.map((assignment) => assignment.routeId),
)
const portalLayerRefinementLockedRouteMask = Int8Array.from(
routableConnections,
({ connection, solvedRoute }, routeId) => {
const explicitLock = getConnectionPortalLayerRefinementLock(connection)
return explicitLock === true ||
(explicitLock === undefined &&
solvedRoute === undefined &&
initiallyAssignedRouteIds.has(routeId))
? 1
: 0
},
)

const problem: TinyHyperGraphProblem = {
routeCount,
Expand All @@ -607,6 +702,7 @@ export const loadSerializedHyperGraph = (
routeNet,
regionNetId,
...(initialAssignments.length > 0 && { initialAssignments }),
portalLayerRefinementLockedRouteMask,
}

const solvedRoutePathSegments: TinyHyperGraphSolution["solvedRoutePathSegments"] =
Expand Down
18 changes: 14 additions & 4 deletions lib/computeRegionCost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ export const isKnownSingleLayerMask = (regionAvailableZMask: number) =>
regionAvailableZMask > 0 &&
(regionAvailableZMask & (regionAvailableZMask - 1)) === 0

export const computeEstimatedViaDemand = (
numSameLayerIntersections: number,
numCrossLayerIntersections: number,
numEntryExitChanges: number,
) =>
numSameLayerIntersections * 2 +
numCrossLayerIntersections +
numEntryExitChanges

export const computeRegionCost = (
regionWidth: number,
regionHeight: number,
Expand Down Expand Up @@ -39,10 +48,11 @@ export const computeRegionCostForArea = (
regionAvailableZMask = 0,
minViaPadDiameter = DEFAULT_MIN_VIA_PAD_DIAMETER,
) => {
const estViasRequired =
numSameLayerIntersections * 2 +
numCrossLayerIntersections * 1 +
numEntryExitChanges * 1
const estViasRequired = computeEstimatedViaDemand(
numSameLayerIntersections,
numCrossLayerIntersections,
numEntryExitChanges,
)
const viaSizeWithMargin = minViaPadDiameter + TRACE_VIA_MARGIN
const viaSizeWithMarginSq = viaSizeWithMargin ** 2

Expand Down
19 changes: 19 additions & 0 deletions lib/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,19 @@ export interface TinyHyperGraphTopology {
portY: Float64Array
portZ: Int32Array

/**
* Numeric physical portal-group metadata. Ports without a replaceable
* physical portal group contain -1.
*/
portPhysicalGroupId?: Int32Array
physicalPortalGroupCount?: number
/**
* Flat lookup indexed by physicalGroupId * physicalGroupLayerCount + z.
* Missing group/layer copies contain -1.
*/
physicalGroupPortIdByZ?: Int32Array
physicalGroupLayerCount?: number

portMetadata?: any[]
}

Expand Down Expand Up @@ -153,6 +166,12 @@ export interface TinyHyperGraphProblem {
* state and may be ripped and rerouted by the normal solver machinery.
*/
initialAssignments?: TinyHyperGraphInitialAssignment[]

/**
* Routes whose serialized initial assignments or other fixed topology must
* not be changed by fixed-topology portal-layer refinement.
*/
portalLayerRefinementLockedRouteMask?: Int8Array
}

export interface TinyHyperGraphProblemSetup {
Expand Down
Loading
Loading