recursive partitioning WIP
This commit is contained in:
parent
3d2635f379
commit
c22a45ae89
@ -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()
|
||||||
|
@ -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),
|
||||||
|
Loading…
Reference in New Issue
Block a user