recursive partitioning WIP

This commit is contained in:
SpaceCat-Chan 2022-12-06 07:39:30 +01:00 committed by Lofty
parent 3d2635f379
commit c22a45ae89
2 changed files with 379 additions and 173 deletions

View File

@ -196,16 +196,46 @@ fn route(ctx: &mut npnr::Context, pressure: f32, history: f32) -> bool {
special_arcs.len().to_string().bold() special_arcs.len().to_string().bold()
); );
let (x_part, y_part, ne, se, sw, nw) = partition::find_partition_point_and_sanity_check( let mut partitions = vec![(
ctx, Coord::new(0, 0),
&nets, Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()),
&partitionable_arcs[..], partitionable_arcs,
pips, String::from(""),
0, )];
ctx.grid_dim_x(),
0, for _ in 0..2 {
ctx.grid_dim_y(), let mut new_partitions = Vec::with_capacity(partitions.len() * 4);
); for (min, max, partition, name) in &partitions {
let (x_part, y_part, ne, se, sw, nw) = partition::find_partition_point_and_sanity_check(
ctx, &nets, partition, pips, min.x, max.x, min.y, max.y,
);
new_partitions.push((
*min,
Coord::new(x_part + 1, y_part + 1),
ne,
format!("{}_NE", name),
));
new_partitions.push((
Coord::new(x_part - 1, min.y),
Coord::new(max.x, y_part + 1),
se,
format!("{}_SE", name),
));
new_partitions.push((
Coord::new(x_part - 1, y_part - 1),
*max,
sw,
format!("{}_SW", name),
));
new_partitions.push((
Coord::new(min.x, y_part - 1),
Coord::new(x_part + 1, max.y),
nw,
format!("{}_NW", name),
));
}
partitions = new_partitions;
}
let time = format!("{:.2}", (Instant::now() - start).as_secs_f32()); let time = format!("{:.2}", (Instant::now() - start).as_secs_f32());
log_info!("Partitioning took {}s\n", time.bold()); log_info!("Partitioning took {}s\n", time.bold());
@ -222,33 +252,6 @@ fn route(ctx: &mut npnr::Context, pressure: f32, history: f32) -> bool {
let progress = MultiProgress::new(); let progress = MultiProgress::new();
let partitions = [
(
Coord::new(0, 0),
Coord::new(x_part + 1, y_part + 1),
&ne,
"NE",
),
(
Coord::new(x_part - 1, 0),
Coord::new(ctx.grid_dim_x(), y_part + 1),
&se,
"SE",
),
(
Coord::new(x_part - 1, y_part - 1),
Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()),
&sw,
"SW",
),
(
Coord::new(0, y_part - 1),
Coord::new(x_part + 1, ctx.grid_dim_y()),
&nw,
"NW",
),
];
let mut router = route::Router::new(&nets, wires, pressure, history); let mut router = route::Router::new(&nets, wires, pressure, history);
partitions partitions
.par_iter() .par_iter()

View File

@ -13,6 +13,7 @@ use crate::{
route::Arc, route::Arc,
}; };
#[derive(Clone, Copy)]
pub enum Segment { pub enum Segment {
Northeast, Northeast,
Southeast, Southeast,
@ -45,8 +46,8 @@ pub enum FullSegment {
// (x > P.x) // (x > P.x)
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Coord { pub struct Coord {
x: i32, pub x: i32,
y: i32, pub y: i32,
} }
impl Coord { impl Coord {
@ -395,8 +396,6 @@ fn partition(
progress.set_message(format!("overused wires: {}", overused_wires)); progress.set_message(format!("overused wires: {}", overused_wires));
let overuse = Mutex::new(HashMap::new());
let arcs = arcs let arcs = arcs
.into_par_iter() .into_par_iter()
.progress_with(progress) .progress_with(progress)
@ -421,8 +420,8 @@ fn partition(
} else if source_is_north != sink_is_north && source_is_east == sink_is_east { } else if source_is_north != sink_is_north && source_is_east == sink_is_east {
let middle = (x, (source_coords.y + sink_coords.y) / 2); let middle = (x, (source_coords.y + sink_coords.y) / 2);
let mut middle = ( let mut middle = (
middle.0.clamp(1, ctx.grid_dim_x() - 1), middle.0.clamp(x_bounds.0 + 1, x_bounds.1 - 1),
middle.1.clamp(1, ctx.grid_dim_y() - 1), middle.1.clamp(y_bounds.0 + 1, y_bounds.1 - 1),
); );
// need to avoid the partition point // need to avoid the partition point
if middle.1 == y { if middle.1 == y {
@ -437,36 +436,92 @@ fn partition(
nets.net_from_index(arc.net()), nets.net_from_index(arc.net()),
); );
if verbose { if let Some(selected_pip) = selected_pip {
log_info!( if verbose {
"split arc {} to {} vertically across pip {}\n", log_info!(
ctx.name_of_wire(arc.source_wire()).to_str().unwrap(), "split arc {} to {} vertically across pip {}\n",
ctx.name_of_wire(arc.sink_wire()).to_str().unwrap(), ctx.name_of_wire(arc.source_wire()).to_str().unwrap(),
ctx.name_of_pip(selected_pip).to_str().unwrap() ctx.name_of_wire(arc.sink_wire()).to_str().unwrap(),
); ctx.name_of_pip(selected_pip).to_str().unwrap()
} );
}
let mut overuse = overuse.lock().unwrap(); let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip);
if let Some(entry) = overuse.get_mut(&ctx.pip_dst_wire(selected_pip)) { let (seg1, seg2) = match (source_is_north, source_is_east) {
*entry += 1; (true, true) => (Segment::Northeast, Segment::Southeast),
(true, false) => (Segment::Northwest, Segment::Southwest),
(false, true) => (Segment::Southeast, Segment::Northeast),
(false, false) => (Segment::Southwest, Segment::Northwest),
};
part_horiz.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
vec![(seg1, src_to_pip), (seg2, pip_to_dst)]
} else { } else {
overuse.insert(ctx.pip_dst_wire(selected_pip), 1); // oh god this is horrible i hate this
} let (seg1, seg2, seg3, seg4) = match (source_is_north, source_is_east) {
(true, true) => (
Segment::Northeast,
Segment::Northwest,
Segment::Southwest,
Segment::Southeast,
),
(true, false) => (
Segment::Northwest,
Segment::Northeast,
Segment::Southeast,
Segment::Southwest,
),
(false, true) => (
Segment::Southeast,
Segment::Southwest,
Segment::Northwest,
Segment::Northeast,
),
(false, false) => (
Segment::Southwest,
Segment::Southeast,
Segment::Northeast,
Segment::Northwest,
),
};
let pip1 = pip_selector
.segment_based_find_pip(
ctx,
seg1,
seg2,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed backup pip selection for horizontal partition");
let pip2 = pip_selector
.segment_based_find_pip(
ctx,
seg2,
seg3,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed backup pip selection for horizontal partition");
let pip3 = pip_selector
.segment_based_find_pip(
ctx,
seg3,
seg4,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed backup pip selection for horizontal partition");
let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip); let (arc1, rest) = arc.split(ctx, pip1);
let (seg1, seg2) = match (source_is_north, source_is_east) { let (arc2, rest) = rest.split(ctx, pip2);
(true, true) => (Segment::Northeast, Segment::Southeast), let (arc3, arc4) = rest.split(ctx, pip3);
(true, false) => (Segment::Northwest, Segment::Southwest),
(false, true) => (Segment::Southeast, Segment::Northeast), vec![(seg1, arc1), (seg2, arc2), (seg3, arc3), (seg4, arc4)]
(false, false) => (Segment::Southwest, Segment::Northwest), }
};
part_horiz.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
vec![(seg1, src_to_pip), (seg2, pip_to_dst)]
} else if source_is_north == sink_is_north && source_is_east != sink_is_east { } else if source_is_north == sink_is_north && source_is_east != sink_is_east {
let middle = ((source_coords.x + sink_coords.x) / 2, y); let middle = ((source_coords.x + sink_coords.x) / 2, y);
let mut middle = ( let mut middle = (
middle.0.clamp(1, ctx.grid_dim_x() - 1), middle.0.clamp(x_bounds.0 + 1, x_bounds.1 - 1),
middle.1.clamp(1, ctx.grid_dim_y() - 1), middle.1.clamp(y_bounds.0 + 1, y_bounds.1 - 1),
); );
// need to avoid the partition point // need to avoid the partition point
if middle.0 == x { if middle.0 == x {
@ -481,41 +536,97 @@ fn partition(
nets.net_from_index(arc.net()), nets.net_from_index(arc.net()),
); );
if verbose { if let Some(selected_pip) = selected_pip {
log_info!( if verbose {
"split arc {} to {} horizontally across pip {}\n", log_info!(
ctx.name_of_wire(arc.source_wire()).to_str().unwrap(), "split arc {} to {} horizontally across pip {}\n",
ctx.name_of_wire(arc.sink_wire()).to_str().unwrap(), ctx.name_of_wire(arc.source_wire()).to_str().unwrap(),
ctx.name_of_pip(selected_pip).to_str().unwrap() ctx.name_of_wire(arc.sink_wire()).to_str().unwrap(),
); ctx.name_of_pip(selected_pip).to_str().unwrap()
} );
}
let mut overuse = overuse.lock().unwrap(); let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip);
if let Some(entry) = overuse.get_mut(&ctx.pip_dst_wire(selected_pip)) { let (seg1, seg2) = match (source_is_north, source_is_east) {
*entry += 1; (true, true) => (Segment::Northeast, Segment::Northwest),
(true, false) => (Segment::Northwest, Segment::Northeast),
(false, true) => (Segment::Southeast, Segment::Southwest),
(false, false) => (Segment::Southwest, Segment::Southeast),
};
part_vert.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
vec![(seg1, src_to_pip), (seg2, pip_to_dst)]
} else { } else {
overuse.insert(ctx.pip_dst_wire(selected_pip), 1); // aaaaaaaa
} let (seg1, seg2, seg3, seg4) = match (source_is_north, source_is_east) {
(true, true) => (
Segment::Northeast,
Segment::Southeast,
Segment::Southwest,
Segment::Northwest,
),
(true, false) => (
Segment::Northwest,
Segment::Southwest,
Segment::Southeast,
Segment::Northeast,
),
(false, true) => (
Segment::Southeast,
Segment::Northeast,
Segment::Northwest,
Segment::Southwest,
),
(false, false) => (
Segment::Southwest,
Segment::Northwest,
Segment::Northeast,
Segment::Southeast,
),
};
let pip1 = pip_selector
.segment_based_find_pip(
ctx,
seg1,
seg2,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed backup pip selection for vertical partition");
let pip2 = pip_selector
.segment_based_find_pip(
ctx,
seg2,
seg3,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed backup pip selection for vertical partition");
let pip3 = pip_selector
.segment_based_find_pip(
ctx,
seg3,
seg4,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed backup pip selection for vertical partition");
let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip); let (arc1, rest) = arc.split(ctx, pip1);
let (seg1, seg2) = match (source_is_north, source_is_east) { let (arc2, rest) = rest.split(ctx, pip2);
(true, true) => (Segment::Northeast, Segment::Northwest), let (arc3, arc4) = rest.split(ctx, pip3);
(true, false) => (Segment::Northwest, Segment::Northeast),
(false, true) => (Segment::Southeast, Segment::Southwest), vec![(seg1, arc1), (seg2, arc2), (seg3, arc3), (seg4, arc4)]
(false, false) => (Segment::Southwest, Segment::Southeast), }
};
part_vert.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
vec![(seg1, src_to_pip), (seg2, pip_to_dst)]
} else { } else {
let middle_horiz = (x, split_line_over_x((source_loc, sink_loc), x)); let middle_horiz = (x, split_line_over_x((source_loc, sink_loc), x));
let mut middle_horiz = ( let mut middle_horiz = (
middle_horiz.0.clamp(1, ctx.grid_dim_x() - 1), middle_horiz.0.clamp(x_bounds.0 + 1, x_bounds.1 - 1),
middle_horiz.1.clamp(1, ctx.grid_dim_y() - 1), middle_horiz.1.clamp(y_bounds.0 + 1, y_bounds.1 - 1),
); );
let middle_vert = (split_line_over_y((source_loc, sink_loc), y), y); let middle_vert = (split_line_over_y((source_loc, sink_loc), y), y);
let mut middle_vert = ( let mut middle_vert = (
middle_vert.0.clamp(1, ctx.grid_dim_x() - 1), middle_vert.0.clamp(x_bounds.0 + 1, x_bounds.1 - 1),
middle_vert.1.clamp(1, ctx.grid_dim_y() - 1), middle_vert.1.clamp(y_bounds.0 + 1, y_bounds.1 - 1),
); );
// need to avoid the partition point // need to avoid the partition point
@ -528,44 +639,124 @@ fn partition(
middle_vert.0 = x + 1; middle_vert.0 = x + 1;
} }
} }
let horiz_happens_first = (middle_horiz.1 < y) == source_is_east; let mut horiz_happens_first = (middle_horiz.1 < y) == source_is_east;
let (horiz_pip, vert_pip) = if horiz_happens_first { let grab_segment_order = |horiz_happens_first| match (
let horiz = pip_selector.find_pip( source_is_north,
ctx, source_is_east,
middle_horiz.into(), horiz_happens_first,
source_loc, ) {
arc.net(), (true, true, true) => {
nets.net_from_index(arc.net()), (Segment::Northeast, Segment::Southeast, Segment::Southwest)
); }
( (true, false, true) => {
horiz, (Segment::Northwest, Segment::Southwest, Segment::Southeast)
pip_selector.find_pip( }
(false, true, true) => {
(Segment::Southeast, Segment::Northeast, Segment::Northwest)
}
(false, false, true) => {
(Segment::Southwest, Segment::Northwest, Segment::Northeast)
}
(true, true, false) => {
(Segment::Northeast, Segment::Northwest, Segment::Southwest)
}
(true, false, false) => {
(Segment::Northwest, Segment::Northeast, Segment::Southeast)
}
(false, true, false) => {
(Segment::Southeast, Segment::Southwest, Segment::Northwest)
}
(false, false, false) => {
(Segment::Southwest, Segment::Southeast, Segment::Northeast)
}
};
let results = (|| {
if horiz_happens_first {
let horiz = pip_selector.find_pip(
ctx,
middle_horiz.into(),
source_loc,
arc.net(),
nets.net_from_index(arc.net()),
)?;
let vert = pip_selector.find_pip(
ctx, ctx,
middle_vert.into(), middle_vert.into(),
middle_horiz.into(), middle_horiz.into(),
arc.net(), arc.net(),
nets.net_from_index(arc.net()), nets.net_from_index(arc.net()),
), )?;
) Some((horiz, vert))
} else {
let vert = pip_selector.find_pip(
ctx,
middle_vert.into(),
source_loc,
arc.net(),
nets.net_from_index(arc.net()),
)?;
let horiz = pip_selector.find_pip(
ctx,
middle_horiz.into(),
middle_vert.into(),
arc.net(),
nets.net_from_index(arc.net()),
)?;
Some((horiz, vert))
}
})();
let (horiz_pip, vert_pip) = if let Some(res) = results {
res
} else { } else {
let vert = pip_selector.find_pip( // forced to flip things the other way around
ctx, horiz_happens_first = !horiz_happens_first;
middle_vert.into(), let (seg1, seg2, seg3) = grab_segment_order(horiz_happens_first);
source_loc, if horiz_happens_first {
arc.net(), (
nets.net_from_index(arc.net()), pip_selector
); .segment_based_find_pip(
( ctx,
pip_selector.find_pip( seg1,
ctx, seg2,
middle_horiz.into(), arc.net(),
middle_vert.into(), nets.net_from_index(arc.net()),
arc.net(), )
nets.net_from_index(arc.net()), .expect("failed to get pip for diagonal partition"),
), pip_selector
vert, .segment_based_find_pip(
) ctx,
seg2,
seg3,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed to get pip for diagonal partition"),
)
} else {
(
pip_selector
.segment_based_find_pip(
ctx,
seg2,
seg3,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed to get pip for diagonal partition"),
pip_selector
.segment_based_find_pip(
ctx,
seg1,
seg2,
arc.net(),
nets.net_from_index(arc.net()),
)
.expect("failed to get pip for diagonal partition"),
)
}
}; };
if verbose { if verbose {
@ -578,18 +769,6 @@ fn partition(
); );
} }
let mut overuse = overuse.lock().unwrap();
if let Some(entry) = overuse.get_mut(&ctx.pip_dst_wire(horiz_pip)) {
*entry += 1;
} else {
overuse.insert(ctx.pip_dst_wire(horiz_pip), 1);
}
if let Some(entry) = overuse.get_mut(&ctx.pip_dst_wire(vert_pip)) {
*entry += 1;
} else {
overuse.insert(ctx.pip_dst_wire(vert_pip), 1);
}
let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = if horiz_happens_first { let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = if horiz_happens_first {
let (a, b) = arc.split(ctx, horiz_pip); let (a, b) = arc.split(ctx, horiz_pip);
let (b, c) = b.split(ctx, vert_pip); let (b, c) = b.split(ctx, vert_pip);
@ -600,33 +779,7 @@ fn partition(
(a, b, c) (a, b, c)
}; };
let (seg1, seg2, seg3) = let (seg1, seg2, seg3) = grab_segment_order(horiz_happens_first);
match (source_is_north, source_is_east, horiz_happens_first) {
(true, true, true) => {
(Segment::Northeast, Segment::Southeast, Segment::Southwest)
}
(true, false, true) => {
(Segment::Northwest, Segment::Southwest, Segment::Southeast)
}
(false, true, true) => {
(Segment::Southeast, Segment::Northeast, Segment::Northwest)
}
(false, false, true) => {
(Segment::Southwest, Segment::Northwest, Segment::Northeast)
}
(true, true, false) => {
(Segment::Northeast, Segment::Northwest, Segment::Southwest)
}
(true, false, false) => {
(Segment::Northwest, Segment::Northeast, Segment::Southeast)
}
(false, true, false) => {
(Segment::Southeast, Segment::Southwest, Segment::Northwest)
}
(false, false, false) => {
(Segment::Southwest, Segment::Southeast, Segment::Northeast)
}
};
part_diag.fetch_add(1, std::sync::atomic::Ordering::Relaxed); part_diag.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
vec![ vec![
(seg1, src_to_mid1), (seg1, src_to_mid1),
@ -753,6 +906,11 @@ pub fn find_partition_point_and_sanity_check(
y_start: i32, y_start: i32,
y_finish: i32, y_finish: i32,
) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) { ) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) {
println!(
"bounds: {:?} -> {:?}",
(x_start, y_start),
(x_finish, y_finish)
);
let (x_part, y_part, ne, se, sw, nw) = let (x_part, y_part, ne, se, sw, nw) =
find_partition_point(ctx, nets, arcs, pips, x_start, x_finish, y_start, y_finish); find_partition_point(ctx, nets, arcs, pips, x_start, x_finish, y_start, y_finish);
@ -860,8 +1018,10 @@ impl PipSelector {
for &pip in pips { for &pip in pips {
let loc = ctx.pip_location(pip); let loc = ctx.pip_location(pip);
if (loc.x == partition_point.x || loc.y == partition_point.y) if (loc.x == partition_point.x || loc.y == partition_point.y)
&& (bounds.0 .0..=bounds.0 .1).contains(&loc.x) && loc.x > bounds.0 .0
&& (bounds.1 .0..=bounds.1 .1).contains(&loc.y) && loc.x < bounds.0 .1
&& loc.y > bounds.1 .0
&& loc.y < bounds.1 .1
{ {
//correctly classifying the pips on the partition point is pretty much impossible //correctly classifying the pips on the partition point is pretty much impossible
//just avoid the partition point //just avoid the partition point
@ -1041,6 +1201,7 @@ impl PipSelector {
} }
/// finds a pip hopefully close to `desired_pip_location` which has a source accessable from `coming_from` /// finds a pip hopefully close to `desired_pip_location` which has a source accessable from `coming_from`
/// returns `None` if no pip can be found
fn find_pip( fn find_pip(
&self, &self,
ctx: &npnr::Context, ctx: &npnr::Context,
@ -1048,8 +1209,46 @@ impl PipSelector {
coming_from: npnr::Loc, coming_from: npnr::Loc,
net: npnr::NetIndex, net: npnr::NetIndex,
raw_net: *mut npnr::NetInfo, raw_net: *mut npnr::NetInfo,
) -> npnr::PipId { ) -> Option<npnr::PipId> {
let pip_index = self.find_pip_index(desired_pip_location, coming_from); let pip_index = self.find_pip_index(desired_pip_location, coming_from);
self.raw_find_pip(ctx, pip_index, desired_pip_location, net, raw_net)
}
/// an emergency find pip function for when the exact pip location doesn't matter, only where comes from and goes to
fn segment_based_find_pip(
&self,
ctx: &npnr::Context,
from_segment: Segment,
to_segment: Segment,
net: npnr::NetIndex,
raw_net: *mut npnr::NetInfo,
) -> Option<npnr::PipId> {
let (pip_index, offset) = match (from_segment, to_segment) {
(Segment::Northeast, Segment::Northwest) => (0, (-1, 0)),
(Segment::Southeast, Segment::Southwest) => (1, (1, 0)),
(Segment::Northwest, Segment::Northeast) => (2, (-1, 0)),
(Segment::Southwest, Segment::Southeast) => (3, (1, 0)),
(Segment::Northeast, Segment::Southeast) => (4, (0, -1)),
(Segment::Northwest, Segment::Southwest) => (5, (0, 1)),
(Segment::Southeast, Segment::Northeast) => (6, (0, -1)),
(Segment::Southwest, Segment::Northwest) => (7, (0, 1)),
_ => panic!("tried to find pip between two diagonal or identical segments"),
};
let desired_location = (
self.partition_loc.x + offset.0,
self.partition_loc.y + offset.1,
);
self.raw_find_pip(ctx, pip_index, desired_location.into(), net, raw_net)
}
fn raw_find_pip(
&self,
ctx: &npnr::Context,
pip_index: usize,
desired_pip_location: npnr::Loc,
net: npnr::NetIndex,
raw_net: *mut npnr::NetInfo,
) -> Option<npnr::PipId> {
// adding a scope to avoid holding the lock for too long // adding a scope to avoid holding the lock for too long
{ {
let cache = self.pip_selection_cache[pip_index] let cache = self.pip_selection_cache[pip_index]
@ -1058,14 +1257,19 @@ impl PipSelector {
.read() .read()
.unwrap(); .unwrap();
if let Some(pip) = *cache { if let Some(pip) = *cache {
return pip; return Some(pip);
} }
} }
let pips = &self.pips[pip_index]; let pips = &self.pips[pip_index];
let selected_pip = self let selected_pip = self
.pip_index_to_position_iter(pip_index, (desired_pip_location.x, desired_pip_location.y)) .pip_index_to_position_iter(pip_index, (desired_pip_location.x, desired_pip_location.y))
.flat_map(|pos| pips.get(&pos).unwrap().iter()) .flat_map(|pos| {
pips.get(&pos)
.unwrap_or_else(|| panic!("tried at {:?}", pos))
.iter()
})
.find(|&pip| { .find(|&pip| {
if !ctx.pip_avail_for_net(*pip, raw_net) { if !ctx.pip_avail_for_net(*pip, raw_net) {
return false; return false;
@ -1104,8 +1308,7 @@ impl PipSelector {
*sink = Some(net); *sink = Some(net);
true true
}) })?;
.expect("unable to find a pip");
{ {
let mut cache = self.pip_selection_cache[pip_index] let mut cache = self.pip_selection_cache[pip_index]
@ -1116,7 +1319,7 @@ impl PipSelector {
*cache = Some(*selected_pip); *cache = Some(*selected_pip);
} }
*selected_pip Some(*selected_pip)
} }
/// takes in a desired pip location and where the arc is coming from and figures out which index to use in the `self.pips` array /// takes in a desired pip location and where the arc is coming from and figures out which index to use in the `self.pips` array
@ -1150,7 +1353,7 @@ impl PipSelector {
0 | 2 => ( 0 | 2 => (
(1, 0), (1, 0),
self.partition_loc.x - start_position.0 - 1, self.partition_loc.x - start_position.0 - 1,
start_position.0 - 1, start_position.0 - self.boundaries.0 .0 - 1,
), ),
1 | 3 => ( 1 | 3 => (
(1, 0), (1, 0),
@ -1160,7 +1363,7 @@ impl PipSelector {
4 | 6 => ( 4 | 6 => (
(0, 1), (0, 1),
self.partition_loc.y - start_position.1 - 1, self.partition_loc.y - start_position.1 - 1,
start_position.1 - 1, start_position.1 - self.boundaries.1 .0 - 1,
), ),
5 | 7 => ( 5 | 7 => (
(0, 1), (0, 1),