Source code for circuit_synth.component_placement.wire_routing

"""Wire routing for KiCad schematics.

This module handles the routing of wires between component pins.
"""

from dataclasses import dataclass
from typing import Dict, List, Tuple

from .placement import PlacementNode


[docs] @dataclass class WireSegment: """Represents a wire segment in the schematic.""" start: Tuple[float, float] end: Tuple[float, float] net_name: str connected_pins: List[Tuple[str, str]] # List of (component_ref, pin_number)
[docs] class WireRouter: """Handles routing of wires between components."""
[docs] def __init__(self): """Initialize the wire router.""" self.wire_segments: List[WireSegment] = []
[docs] def route_net( self, net: "Net", placement_nodes: Dict[str, PlacementNode] ) -> List[WireSegment]: """Route wires for a single net.""" if len(net.pins) < 2: return [] print(f"\nRouting net: {net.name}") print(f"Number of pins to connect: {len(net.pins)}") # Get component positions and pin locations connected_points = [] for pin in net.pins: comp = pin.parent node = placement_nodes[comp.ref] # Get pin location relative to component center pin_loc = node.geometry_handler.get_pin_location(pin.number, node.rotation) if pin_loc: # Calculate absolute pin position abs_x = node.x + pin_loc[0] abs_y = node.y + pin_loc[1] print(f"Pin {pin.number} of {comp.ref}:") print(f" Component center: ({node.x}, {node.y})") print(f" Pin offset: ({pin_loc[0]}, {pin_loc[1]})") print(f" Absolute pin position: ({abs_x}, {abs_y})") connected_points.append(((abs_x, abs_y), (comp.ref, pin.number))) # Sort points based on component type and position def sort_key(point_info): point, pin_info = point_info comp_ref = pin_info[0] node = placement_nodes[comp_ref] # Power components should be at their respective ends if node.component.library == "power": if "+3V3" in node.component.name: return -float("inf") # Place 3V3 at start elif "GND" in node.component.name: return float("inf") # Place GND at end return point[1] # Sort other components by y-position connected_points.sort(key=sort_key) # Create wire segments segments = [] for i in range(len(connected_points) - 1): start_point, start_pin = connected_points[i] end_point, end_pin = connected_points[i + 1] # For power connections, ensure proper direction if any( "power" == placement_nodes[pin[0]].component.library for pin in [start_pin, end_pin] ): # Get the power component's pin info power_pin = ( start_pin if placement_nodes[start_pin[0]].component.library == "power" else end_pin ) comp_pin = ( end_pin if placement_nodes[start_pin[0]].component.library == "power" else start_pin ) # Determine wire direction based on power type if "+3V3" in placement_nodes[power_pin[0]].component.name: wire_start = start_point wire_end = end_point else: # GND wire_start = end_point wire_end = start_point segments.append( WireSegment( start=wire_start, end=wire_end, net_name=net.name, connected_pins=[start_pin, end_pin], ) ) # For component-to-component connections, use L-shaped path if needed else: # If points are vertically aligned (within tolerance) if abs(start_point[0] - end_point[0]) < 0.1: segments.append( WireSegment( start=start_point, end=end_point, net_name=net.name, connected_pins=[start_pin, end_pin], ) ) else: print( f"\nRouting between {start_pin[0]} pin {start_pin[1]} and {end_pin[0]} pin {end_pin[1]}" ) print(f"Start point: ({start_point[0]}, {start_point[1]})") print(f"End point: ({end_point[0]}, {end_point[1]})") # Calculate midpoint between components for better routing mid_y = (start_point[1] + end_point[1]) / 2 print(f"Using midpoint y={mid_y} for routing") # Create vertical segments first, then horizontal segments.extend( [ # Vertical segment from start WireSegment( start=start_point, end=(start_point[0], mid_y), net_name=net.name, connected_pins=[start_pin], ), # Horizontal segment WireSegment( start=(start_point[0], mid_y), end=(end_point[0], mid_y), net_name=net.name, connected_pins=[], ), # Vertical segment to end WireSegment( start=(end_point[0], mid_y), end=end_point, net_name=net.name, connected_pins=[end_pin], ), ] ) return segments