Route with copper zones, and let vias into no-tracks areas
freeroute ignored the DSN's planes (KiCad's zones), so it never knew that pads in a pour are joined by it. On the rc4 power stage those pads sit inside "keep router off" areas as well, and every connection to them was dropped without a word. - Read (plane <net> <shape>) and put each zone on the board as a ConductionArea of its net. Zones are not obstacles: KiCad refills them around other nets' copper. - The grid groups each net's pads and zone pieces that copper already joins (a pad in a zone, two zones sharing a pad) and routes only between groups. A connection may end on a zone by a via inside its copper, or by a track where tracks are allowed. - wire_keepout now blocks traces only, as KiCad's "no tracks" rule area does; via_keepout only vias; keepout both, in the grid and in the exact verifier. rc4 power stage, exact engine, resolution 2: 2 unconnected, down from 8 (FreeRouting JAR: 12), no DRC errors.
This commit is contained in:
@@ -31,7 +31,7 @@ from freeroute.geometry.polygon_shape import PolygonShape
|
||||
|
||||
from .board import BasicBoard
|
||||
from .clearance import ClearanceMatrix
|
||||
from .items import ObstacleArea, Pin
|
||||
from .items import ConductionArea, ObstacleArea, Pin
|
||||
from .layer import Layer, LayerStructure
|
||||
from .net import Nets
|
||||
from .transform import CoordinateTransform
|
||||
@@ -55,6 +55,7 @@ def build_board(dsn: DsnBoard) -> BasicBoard:
|
||||
_insert_pins(dsn, board, transform, terminal_to_net)
|
||||
_insert_keepouts(dsn, board, transform)
|
||||
_insert_image_keepouts(dsn, board, transform)
|
||||
_insert_zones(dsn, board, transform, nets)
|
||||
return board
|
||||
|
||||
|
||||
@@ -330,6 +331,8 @@ def _insert_keepouts(dsn: DsnBoard, board: BasicBoard, transform: CoordinateTran
|
||||
name=keepout.area.name,
|
||||
layer=layer_index,
|
||||
tiles=tiles,
|
||||
blocks_wires=keepout.kind != "via_keepout",
|
||||
blocks_vias=keepout.kind != "wire_keepout",
|
||||
)
|
||||
)
|
||||
|
||||
@@ -402,13 +405,17 @@ def _insert_image_keepouts(dsn: DsnBoard, board: BasicBoard, transform: Coordina
|
||||
image = images.get(placement.lib_name)
|
||||
if image is None:
|
||||
continue
|
||||
areas = [*image.keepouts, *image.via_keepouts, *image.wire_keepouts]
|
||||
areas = [
|
||||
*((a, True, True) for a in image.keepouts),
|
||||
*((a, False, True) for a in image.via_keepouts),
|
||||
*((a, True, False) for a in image.wire_keepouts),
|
||||
]
|
||||
if not areas:
|
||||
continue
|
||||
for place in placement.places:
|
||||
if place.x is None or place.y is None:
|
||||
continue
|
||||
for area in areas:
|
||||
for area, blocks_wires, blocks_vias in areas:
|
||||
border = area.border
|
||||
if border is None:
|
||||
continue
|
||||
@@ -423,7 +430,12 @@ def _insert_image_keepouts(dsn: DsnBoard, board: BasicBoard, transform: Coordina
|
||||
top, bottom = min(signal_layers), max(signal_layers)
|
||||
layers = [top + bottom - layer for layer in layers]
|
||||
for layer_index in layers:
|
||||
board.insert(ObstacleArea(name=area.name, layer=layer_index, tiles=tiles))
|
||||
board.insert(
|
||||
ObstacleArea(
|
||||
name=area.name, layer=layer_index, tiles=tiles,
|
||||
blocks_wires=blocks_wires, blocks_vias=blocks_vias,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _placed_area_tiles(shape: Shape, place, transform: CoordinateTransform) -> list:
|
||||
@@ -447,3 +459,29 @@ def _placed_area_tiles(shape: Shape, place, transform: CoordinateTransform) -> l
|
||||
if len(pts) < 3:
|
||||
return []
|
||||
return [tile for tile in PolygonShape(pts).split_to_convex() if not tile.is_empty()]
|
||||
|
||||
|
||||
def _insert_zones(dsn: DsnBoard, board: BasicBoard, transform: CoordinateTransform, nets) -> None:
|
||||
"""Each DSN plane as a ConductionArea of its net on its layer."""
|
||||
layer_no = {layer.name: i for i, layer in enumerate(dsn.layers)}
|
||||
numbers = {net.name: net.net_number for net in nets}
|
||||
for plane in dsn.planes:
|
||||
shape = plane.shape
|
||||
if plane.net not in numbers or shape.layer not in layer_no:
|
||||
continue
|
||||
if not isinstance(shape, (Polygon, Path)):
|
||||
continue
|
||||
c = shape.coords
|
||||
pts = [transform.dsn_to_board_point(c[i], c[i + 1]) for i in range(0, len(c) - 1, 2)]
|
||||
if len(pts) < 3:
|
||||
continue
|
||||
polygon = PolygonShape(pts)
|
||||
tiles = [t for t in polygon.split_to_convex() if not t.is_empty()]
|
||||
if not tiles:
|
||||
continue
|
||||
board.insert(
|
||||
ConductionArea(
|
||||
net_nos=[numbers[plane.net]], name=plane.net, layer=layer_no[shape.layer],
|
||||
tiles=tiles, polygon=polygon, blocks_wires=False, blocks_vias=False,
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user