diff --git a/src/layout.js b/src/layout.js index be7353d..26fed91 100644 --- a/src/layout.js +++ b/src/layout.js @@ -18,7 +18,7 @@ const NET_CLASS_PRIORITY = { const LABEL_TIE_CLASSES = new Set(["power", "ground", "bus"]); const DEFAULT_RENDER_MODE = "schematic_stub"; const ROTATION_STEPS = [0, 90, 180, 270]; -const MIN_CHANNEL_SPACING_STEPS = 2; +const MIN_CHANNEL_SPACING_STEPS = 3; const LANE_ORDER = ["power", "clock", "signal", "analog", "ground", "bus", "differential"]; function toGrid(value) { @@ -1190,7 +1190,7 @@ function uniquePoints(points) { return [...map.values()]; } -function routeLabelTieNet(net, pinNodes, context) { +function routeLabelTieNet(net, pinNodes, context, fallbackReason = null) { const routes = []; const tiePoints = []; @@ -1239,7 +1239,7 @@ function routeLabelTieNet(net, pinNodes, context) { total_bends: 0, detour_ratio: 1, used_label_tie: true, - fallback_reason: null + fallback_reason: fallbackReason } }; } @@ -1493,6 +1493,9 @@ function shouldUseLabelTie(net, pinNodes, context) { const span = Math.abs(maxX - minX) + Math.abs(maxY - minY); if (context.renderMode === "explicit") { + if (context.busNetNames.has(net.name) && (pinNodes.length >= 3 || span > GRID * 36)) { + return true; + } return LABEL_TIE_CLASSES.has(net.class) && pinNodes.length > 2; } @@ -1517,6 +1520,26 @@ function shouldUseLabelTie(net, pinNodes, context) { return false; } +function shouldFallbackToTieByQuality(net, pinNodes, routed) { + if (!routed || routed.mode !== "routed") { + return false; + } + const stats = routed.route_stats ?? {}; + const detour = Number(stats.detour_ratio ?? 1); + const bends = Number(stats.total_bends ?? 0); + const totalLength = Number(stats.total_length ?? 0); + const directLength = Number(stats.direct_length ?? totalLength); + const spanRatio = directLength > 0 ? totalLength / directLength : 1; + + if (pinNodes.length >= 4 && (detour > 2.25 || bends >= 7)) { + return true; + } + if ((net.class === "analog" || net.class === "signal") && pinNodes.length >= 3 && spanRatio > 2.7) { + return true; + } + return false; +} + function routeAllNets(model, placed, placedMap, bounds, options) { const obstacles = buildObstacles(model, placed); const edgeUsage = new Map(); @@ -1551,10 +1574,14 @@ function routeAllNets(model, placed, placedMap, bounds, options) { busNetNames }; - const routed = shouldUseLabelTie(net, pinNodes, routeContext) + let routed = shouldUseLabelTie(net, pinNodes, routeContext) ? routeLabelTieNet(net, pinNodes, routeContext) : routePointToPointNet(net, pinNodes, routeContext); + if (shouldFallbackToTieByQuality(net, pinNodes, routed)) { + routed = routeLabelTieNet(net, pinNodes, routeContext, "quality_policy"); + } + routedByName.set(net.name, { net, isBusMember: busNetNames.has(net.name), diff --git a/tests/baselines/ui/explicit-mode-auto-tidy.png b/tests/baselines/ui/explicit-mode-auto-tidy.png index 1602532..82c864b 100644 Binary files a/tests/baselines/ui/explicit-mode-auto-tidy.png and b/tests/baselines/ui/explicit-mode-auto-tidy.png differ diff --git a/tests/baselines/ui/post-migration-apply.png b/tests/baselines/ui/post-migration-apply.png index 4ba43a6..917701e 100644 Binary files a/tests/baselines/ui/post-migration-apply.png and b/tests/baselines/ui/post-migration-apply.png differ diff --git a/tests/baselines/ui/selected-u2.png b/tests/baselines/ui/selected-u2.png index e52a329..cafef3e 100644 Binary files a/tests/baselines/ui/selected-u2.png and b/tests/baselines/ui/selected-u2.png differ