tiered bbox
This commit is contained in:
parent
c36bce9978
commit
9fac436c50
5 changed files with 45 additions and 15 deletions
|
|
@ -64,7 +64,7 @@ class ComponentResult:
|
|||
self.length = length
|
||||
# Vectorized bounds calculation
|
||||
self.bounds = shapely.bounds(geometry)
|
||||
self.dilated_bounds = shapely.bounds(dilated_geometry) if dilated_geometry else None
|
||||
self.dilated_bounds = shapely.bounds(dilated_geometry) if dilated_geometry is not None else None
|
||||
|
||||
def translate(self, dx: float, dy: float) -> ComponentResult:
|
||||
"""
|
||||
|
|
@ -72,15 +72,16 @@ class ComponentResult:
|
|||
"""
|
||||
# Vectorized translation if possible, else list comp
|
||||
# Shapely 2.x affinity functions still work on single geometries efficiently
|
||||
geoms = self.geometry
|
||||
if self.dilated_geometry:
|
||||
geoms = geoms + self.dilated_geometry
|
||||
geoms = list(self.geometry)
|
||||
num_geom = len(self.geometry)
|
||||
if self.dilated_geometry is not None:
|
||||
geoms.extend(self.dilated_geometry)
|
||||
|
||||
from shapely.affinity import translate
|
||||
translated = [translate(p, dx, dy) for p in geoms]
|
||||
|
||||
new_geom = translated[:len(self.geometry)]
|
||||
new_dil = translated[len(self.geometry):] if self.dilated_geometry else None
|
||||
new_geom = translated[:num_geom]
|
||||
new_dil = translated[num_geom:] if self.dilated_geometry is not None else None
|
||||
|
||||
new_port = Port(self.end_port.x + dx, self.end_port.y + dy, self.end_port.orientation)
|
||||
return ComponentResult(new_geom, new_port, self.length, new_dil)
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ class AStarRouter:
|
|||
target: Port,
|
||||
net_width: float,
|
||||
net_id: str = 'default',
|
||||
bend_collision_type: Literal['arc', 'bbox', 'clipped_bbox'] | None = None,
|
||||
) -> list[ComponentResult] | None:
|
||||
"""
|
||||
Route a single net using A*.
|
||||
|
|
@ -203,10 +204,14 @@ class AStarRouter:
|
|||
target: Target port.
|
||||
net_width: Waveguide width (um).
|
||||
net_id: Optional net identifier.
|
||||
bend_collision_type: Override collision model for this route.
|
||||
|
||||
Returns:
|
||||
List of moves forming the path, or None if failed.
|
||||
"""
|
||||
if bend_collision_type is not None:
|
||||
self.config.bend_collision_type = bend_collision_type
|
||||
|
||||
self._collision_cache.clear()
|
||||
open_set: list[AStarNode] = []
|
||||
# Key: (x, y, orientation) rounded to 1nm
|
||||
|
|
@ -311,7 +316,9 @@ class AStarRouter:
|
|||
res = self._move_cache[abs_key]
|
||||
else:
|
||||
# Level 2: Relative cache (orientation only)
|
||||
rel_key = (base_ori, 'S', length, net_width, self._self_dilation)
|
||||
# Dilation is now 0.0 for caching to save translation time.
|
||||
# It will be calculated lazily in _add_node if needed.
|
||||
rel_key = (base_ori, 'S', length, net_width, 0.0)
|
||||
if rel_key in self._move_cache:
|
||||
res_rel = self._move_cache[rel_key]
|
||||
# Check closed set before translating
|
||||
|
|
@ -322,7 +329,7 @@ class AStarRouter:
|
|||
continue
|
||||
res = res_rel.translate(cp.x, cp.y)
|
||||
else:
|
||||
res_rel = Straight.generate(Port(0, 0, base_ori), length, net_width, dilation=self._self_dilation)
|
||||
res_rel = Straight.generate(Port(0, 0, base_ori), length, net_width, dilation=0.0)
|
||||
self._move_cache[rel_key] = res_rel
|
||||
res = res_rel.translate(cp.x, cp.y)
|
||||
self._move_cache[abs_key] = res
|
||||
|
|
@ -335,7 +342,7 @@ class AStarRouter:
|
|||
if abs_key in self._move_cache:
|
||||
res = self._move_cache[abs_key]
|
||||
else:
|
||||
rel_key = (base_ori, 'B', radius, direction, net_width, self.config.bend_collision_type, self._self_dilation)
|
||||
rel_key = (base_ori, 'B', radius, direction, net_width, self.config.bend_collision_type, 0.0)
|
||||
if rel_key in self._move_cache:
|
||||
res_rel = self._move_cache[rel_key]
|
||||
# Check closed set before translating
|
||||
|
|
@ -353,7 +360,7 @@ class AStarRouter:
|
|||
direction,
|
||||
collision_type=self.config.bend_collision_type,
|
||||
clip_margin=self.config.bend_clip_margin,
|
||||
dilation=self._self_dilation
|
||||
dilation=0.0
|
||||
)
|
||||
self._move_cache[rel_key] = res_rel
|
||||
res = res_rel.translate(cp.x, cp.y)
|
||||
|
|
@ -367,7 +374,7 @@ class AStarRouter:
|
|||
if abs_key in self._move_cache:
|
||||
res = self._move_cache[abs_key]
|
||||
else:
|
||||
rel_key = (base_ori, 'SB', offset, radius, net_width, self.config.bend_collision_type, self._self_dilation)
|
||||
rel_key = (base_ori, 'SB', offset, radius, net_width, self.config.bend_collision_type, 0.0)
|
||||
if rel_key in self._move_cache:
|
||||
res_rel = self._move_cache[rel_key]
|
||||
# Check closed set before translating
|
||||
|
|
@ -386,7 +393,7 @@ class AStarRouter:
|
|||
width=net_width,
|
||||
collision_type=self.config.bend_collision_type,
|
||||
clip_margin=self.config.bend_clip_margin,
|
||||
dilation=self._self_dilation
|
||||
dilation=0.0
|
||||
)
|
||||
self._move_cache[rel_key] = res_rel
|
||||
res = res_rel.translate(cp.x, cp.y)
|
||||
|
|
@ -424,9 +431,20 @@ class AStarRouter:
|
|||
if self._collision_cache[cache_key]:
|
||||
return
|
||||
else:
|
||||
# Lazy Dilation: compute dilated polygons only if we need a collision check
|
||||
if result.dilated_geometry is None:
|
||||
# We need to update the ComponentResult with dilated geometry
|
||||
# For simplicity, we'll just buffer the polygons here.
|
||||
# In a more optimized version, ComponentResult might have a .dilate() method.
|
||||
dilated = [p.buffer(self._self_dilation) for p in result.geometry]
|
||||
result.dilated_geometry = dilated
|
||||
# Re-calculate dilated bounds
|
||||
import shapely
|
||||
result.dilated_bounds = shapely.bounds(dilated)
|
||||
|
||||
hard_coll = False
|
||||
for i, poly in enumerate(result.geometry):
|
||||
dil_poly = result.dilated_geometry[i] if result.dilated_geometry else None
|
||||
dil_poly = result.dilated_geometry[i]
|
||||
if self.cost_evaluator.collision_engine.check_collision(
|
||||
poly, net_id, buffer_mode='static', start_port=parent.port, end_port=result.end_port,
|
||||
dilated_geometry=dil_poly
|
||||
|
|
@ -437,6 +455,13 @@ class AStarRouter:
|
|||
if hard_coll:
|
||||
return
|
||||
|
||||
# Lazy Dilation for self-intersection and cost evaluation
|
||||
if result.dilated_geometry is None:
|
||||
dilated = [p.buffer(self._self_dilation) for p in result.geometry]
|
||||
result.dilated_geometry = dilated
|
||||
import shapely
|
||||
result.dilated_bounds = shapely.bounds(dilated)
|
||||
|
||||
# 3. Check for Self-Intersection (Limited to last 100 segments for performance)
|
||||
if result.dilated_geometry:
|
||||
# Union of current move's bounds for fast path-wide pruning
|
||||
|
|
|
|||
|
|
@ -111,9 +111,13 @@ class PathFinder:
|
|||
self.cost_evaluator.collision_engine.remove_path(net_id)
|
||||
|
||||
# 2. Reroute with current congestion info
|
||||
# Tiered Strategy: use clipped_bbox for Iteration 0 for speed.
|
||||
# Switch to arc for higher iterations if collisions persist.
|
||||
coll_model = "clipped_bbox" if iteration == 0 else "arc"
|
||||
|
||||
net_start = time.monotonic()
|
||||
path = self.router.route(start, target, width, net_id=net_id)
|
||||
logger.debug(f' Net {net_id} routed in {time.monotonic() - net_start:.4f}s')
|
||||
path = self.router.route(start, target, width, net_id=net_id, bend_collision_type=coll_model)
|
||||
logger.debug(f' Net {net_id} routed in {time.monotonic() - net_start:.4f}s using {coll_model}')
|
||||
|
||||
if path:
|
||||
# 3. Add to index
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue