mirror of https://codeberg.org/topola/topola.git
feat(autorouter/presorter): Take into account ratline-pad intersections
This commit is contained in:
parent
1b485e81a6
commit
aee8c42720
|
|
@ -168,7 +168,6 @@ impl SpecctraMesadata {
|
||||||
/// associated with a net class. If a net class is found, it retrieves the corresponding rule
|
/// associated with a net class. If a net class is found, it retrieves the corresponding rule
|
||||||
/// from the class rules. If no class is associated, or if the class does not have a defined rule,
|
/// from the class rules. If no class is associated, or if the class does not have a defined rule,
|
||||||
/// it defaults to the general structure rule.
|
/// it defaults to the general structure rule.
|
||||||
///
|
|
||||||
pub fn get_rule(&self, net: usize) -> &SpecctraRule {
|
pub fn get_rule(&self, net: usize) -> &SpecctraRule {
|
||||||
self.net_netclass
|
self.net_netclass
|
||||||
.get(&net)
|
.get(&net)
|
||||||
|
|
@ -179,10 +178,10 @@ impl SpecctraMesadata {
|
||||||
|
|
||||||
impl AccessRules for SpecctraMesadata {
|
impl AccessRules for SpecctraMesadata {
|
||||||
fn clearance(&self, conditions1: &Conditions<'_>, conditions2: &Conditions<'_>) -> f64 {
|
fn clearance(&self, conditions1: &Conditions<'_>, conditions2: &Conditions<'_>) -> f64 {
|
||||||
let clr1 = self.get_rule(conditions1.net).clearance;
|
let clearance1 = self.get_rule(conditions1.net).clearance;
|
||||||
let clr2 = self.get_rule(conditions2.net).clearance;
|
let clearance2 = self.get_rule(conditions2.net).clearance;
|
||||||
|
|
||||||
f64::max(clr1, clr2)
|
f64::max(clearance1, clearance2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn largest_clearance(&self, _maybe_net: Option<usize>) -> f64 {
|
fn largest_clearance(&self, _maybe_net: Option<usize>) -> f64 {
|
||||||
|
|
|
||||||
|
|
@ -63,10 +63,10 @@ impl SccIntersectionsAndLengthPresorter {
|
||||||
&& a.contains(&filtered_ratsnest.edge_endpoints(*ratline).unwrap().1)
|
&& a.contains(&filtered_ratsnest.edge_endpoints(*ratline).unwrap().1)
|
||||||
{
|
{
|
||||||
a_length += ratline.ref_(autorouter).length();
|
a_length += ratline.ref_(autorouter).length();
|
||||||
a_intersector_count += ratline
|
a_intersector_count +=
|
||||||
.ref_(autorouter)
|
ratline.ref_(autorouter).interiorly_cut_ratlines().count();
|
||||||
.interior_obstacle_ratlines()
|
a_intersector_count +=
|
||||||
.count();
|
ratline.ref_(autorouter).cut_other_net_primitives().count();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,10 +75,10 @@ impl SccIntersectionsAndLengthPresorter {
|
||||||
&& b.contains(&filtered_ratsnest.edge_endpoints(*ratline).unwrap().1)
|
&& b.contains(&filtered_ratsnest.edge_endpoints(*ratline).unwrap().1)
|
||||||
{
|
{
|
||||||
b_length += ratline.ref_(autorouter).length();
|
b_length += ratline.ref_(autorouter).length();
|
||||||
b_intersector_count += ratline
|
b_intersector_count +=
|
||||||
.ref_(autorouter)
|
ratline.ref_(autorouter).interiorly_cut_ratlines().count();
|
||||||
.interior_obstacle_ratlines()
|
b_intersector_count +=
|
||||||
.count();
|
ratline.ref_(autorouter).cut_other_net_primitives().count();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,12 @@ use petgraph::graph::{EdgeIndex, NodeIndex};
|
||||||
use specctra_core::mesadata::AccessMesadata;
|
use specctra_core::mesadata::AccessMesadata;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{band::BandTermsegIndex, dot::FixedDotIndex},
|
drawing::{
|
||||||
geometry::shape::MeasureLength,
|
band::BandTermsegIndex,
|
||||||
|
dot::FixedDotIndex,
|
||||||
|
graph::{GetMaybeNet, MakePrimitive, PrimitiveIndex},
|
||||||
|
},
|
||||||
|
geometry::{shape::MeasureLength, GetLayer},
|
||||||
graph::MakeRef,
|
graph::MakeRef,
|
||||||
triangulation::GetTrianvertexNodeIndex,
|
triangulation::GetTrianvertexNodeIndex,
|
||||||
};
|
};
|
||||||
|
|
@ -84,16 +88,40 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
|
||||||
(source_dot, target_dot)
|
(source_dot, target_dot)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn closure_obstacle_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
pub fn layer(&self) -> usize {
|
||||||
self.intersecting_ratlines()
|
self.endpoint_dots()
|
||||||
|
.0
|
||||||
|
.primitive(self.autorouter.board().layout().drawing())
|
||||||
|
.layer()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interior_obstacle_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
pub fn net(&self) -> usize {
|
||||||
self.intersecting_ratlines()
|
self.endpoint_dots()
|
||||||
.filter(|index| !self.is_pin_cutter(*index))
|
.0
|
||||||
|
.primitive(self.autorouter.board().layout().drawing())
|
||||||
|
.maybe_net()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersecting_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
fn cut_primitives(&self) -> impl Iterator<Item = PrimitiveIndex> + '_ {
|
||||||
|
self.autorouter
|
||||||
|
.board()
|
||||||
|
.layout()
|
||||||
|
.drawing()
|
||||||
|
.cut(self.line_segment(), 0.0, self.layer())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cut_other_net_primitives(&self) -> impl Iterator<Item = PrimitiveIndex> + '_ {
|
||||||
|
self.cut_primitives().filter(|primitive_node| {
|
||||||
|
primitive_node
|
||||||
|
.primitive(self.autorouter.board().layout().drawing())
|
||||||
|
.maybe_net()
|
||||||
|
.map(|net| net != self.net())
|
||||||
|
.unwrap_or(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn interiorly_cut_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
||||||
let self_line_segment = self.line_segment();
|
let self_line_segment = self.line_segment();
|
||||||
|
|
||||||
self.autorouter
|
self.autorouter
|
||||||
|
|
@ -112,18 +140,6 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
|
||||||
.filter(move |other| {
|
.filter(move |other| {
|
||||||
let other_line_segment = other.ref_(self.autorouter).line_segment();
|
let other_line_segment = other.ref_(self.autorouter).line_segment();
|
||||||
|
|
||||||
line_intersection(self_line_segment, other_line_segment).is_some()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_pin_cutter(&self, other: RatlineIndex) -> bool {
|
|
||||||
// TODO: For now, instead of detecting whether endpoint ratvertex pins
|
|
||||||
// are cut, we only check if the intersection between self and the
|
|
||||||
// supposed cutter is not internal.
|
|
||||||
|
|
||||||
let self_line_segment = self.line_segment();
|
|
||||||
let other_line_segment = other.ref_(self.autorouter).line_segment();
|
|
||||||
|
|
||||||
if let Some(LineIntersection::SinglePoint { is_proper, .. }) =
|
if let Some(LineIntersection::SinglePoint { is_proper, .. }) =
|
||||||
line_intersection(self_line_segment, other_line_segment)
|
line_intersection(self_line_segment, other_line_segment)
|
||||||
{
|
{
|
||||||
|
|
@ -133,6 +149,7 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn line_segment(&self) -> Line {
|
pub fn line_segment(&self) -> Line {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use geo::Line;
|
||||||
use petgraph::visit::Walker;
|
use petgraph::visit::Walker;
|
||||||
use specctra_core::rules::GetConditions;
|
use specctra_core::rules::GetConditions;
|
||||||
|
|
||||||
|
|
@ -11,7 +12,10 @@ use crate::{
|
||||||
primitive::MakePrimitiveShape,
|
primitive::MakePrimitiveShape,
|
||||||
Collision, Infringement,
|
Collision, Infringement,
|
||||||
},
|
},
|
||||||
geometry::{primitive::AccessPrimitiveShape, GenericNode, GetLayer},
|
geometry::{
|
||||||
|
primitive::{AccessPrimitiveShape, PrimitiveShape, SegShape},
|
||||||
|
GenericNode, GetLayer,
|
||||||
|
},
|
||||||
graph::GenericIndex,
|
graph::GenericIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -112,6 +116,36 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cut(
|
||||||
|
&self,
|
||||||
|
line: Line,
|
||||||
|
width: f64,
|
||||||
|
layer: usize,
|
||||||
|
) -> impl Iterator<Item = PrimitiveIndex> + '_ {
|
||||||
|
let limiting_shape = PrimitiveShape::Seg(SegShape {
|
||||||
|
from: line.start_point(),
|
||||||
|
to: line.end_point(),
|
||||||
|
width,
|
||||||
|
})
|
||||||
|
.inflate(self.rules().largest_clearance(None));
|
||||||
|
|
||||||
|
self.recording_geometry_with_rtree()
|
||||||
|
.rtree()
|
||||||
|
.locate_in_envelope_intersecting(&limiting_shape.envelope_3d(width, layer))
|
||||||
|
.filter_map(|wrapper| {
|
||||||
|
if let GenericNode::Primitive(primitive_node) = wrapper.data {
|
||||||
|
Some(primitive_node)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter_map(move |primitive_node| {
|
||||||
|
limiting_shape
|
||||||
|
.intersects(&primitive_node.primitive(self).shape())
|
||||||
|
.then_some(primitive_node)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn find_infringement_except<'a>(
|
pub(super) fn find_infringement_except<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
infringer: PrimitiveIndex,
|
infringer: PrimitiveIndex,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ pub trait AccessPrimitiveShape: AccessShape + GetWidth {
|
||||||
[
|
[
|
||||||
envelope.upper()[0],
|
envelope.upper()[0],
|
||||||
envelope.upper()[1],
|
envelope.upper()[1],
|
||||||
|
// XXX: Why isn't floating point infinity used here?
|
||||||
(layer_count - 1) as f64,
|
(layer_count - 1) as f64,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue