make slight improvement to partitioner
This commit is contained in:
parent
6194b6dbcf
commit
90f0630e62
@ -161,7 +161,6 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
|
|
||||||
let (x_part, y_part, ne, se, sw, nw, misc) = partition::find_partition_point_and_sanity_check(
|
let (x_part, y_part, ne, se, sw, nw, misc) = partition::find_partition_point_and_sanity_check(
|
||||||
ctx,
|
ctx,
|
||||||
&nets,
|
|
||||||
&arcs[..],
|
&arcs[..],
|
||||||
pips,
|
pips,
|
||||||
0,
|
0,
|
||||||
@ -180,10 +179,22 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
let progress = MultiProgress::new();
|
let progress = MultiProgress::new();
|
||||||
|
|
||||||
let partitions = [
|
let partitions = [
|
||||||
(Coord::new(0, 0), Coord::new(x_part+1, y_part+1), &ne),
|
(Coord::new(0, 0), Coord::new(x_part + 1, y_part + 1), &ne),
|
||||||
(Coord::new(x_part-1, 0), Coord::new(ctx.grid_dim_x(), y_part+1), &se),
|
(
|
||||||
(Coord::new(x_part-1, y_part-1), Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()), &sw),
|
Coord::new(x_part - 1, 0),
|
||||||
(Coord::new(0, y_part-1), Coord::new(x_part+1, ctx.grid_dim_y()), &nw)
|
Coord::new(ctx.grid_dim_x(), y_part + 1),
|
||||||
|
&se,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Coord::new(x_part - 1, y_part - 1),
|
||||||
|
Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()),
|
||||||
|
&sw,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Coord::new(0, y_part - 1),
|
||||||
|
Coord::new(x_part + 1, ctx.grid_dim_y()),
|
||||||
|
&nw,
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
partitions.par_iter().for_each(|(box_ne, box_sw, arcs)| {
|
partitions.par_iter().for_each(|(box_ne, box_sw, arcs)| {
|
||||||
@ -192,12 +203,18 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
});
|
});
|
||||||
|
|
||||||
log_info!("Routing miscellaneous arcs\n");
|
log_info!("Routing miscellaneous arcs\n");
|
||||||
let mut router = route::Router::new(Coord::new(0, 0), Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()));
|
let mut router = route::Router::new(
|
||||||
|
Coord::new(0, 0),
|
||||||
|
Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()),
|
||||||
|
);
|
||||||
router.route(ctx, &nets, &misc, &progress);
|
router.route(ctx, &nets, &misc, &progress);
|
||||||
|
|
||||||
let time = Instant::now() - start;
|
let time = Instant::now() - start;
|
||||||
|
|
||||||
log_info!("Routing took {:.2}s\n", time.as_secs_f32().to_string().bold());
|
log_info!(
|
||||||
|
"Routing took {:.2}s\n",
|
||||||
|
time.as_secs_f32().to_string().bold()
|
||||||
|
);
|
||||||
|
|
||||||
//let mut router = route::Router::new(Coord::new(0, 0), Coord::new(x_part, y_part));
|
//let mut router = route::Router::new(Coord::new(0, 0), Coord::new(x_part, y_part));
|
||||||
|
|
||||||
|
@ -76,7 +76,6 @@ impl From<npnr::Loc> for Coord {
|
|||||||
|
|
||||||
pub fn find_partition_point(
|
pub fn find_partition_point(
|
||||||
ctx: &npnr::Context,
|
ctx: &npnr::Context,
|
||||||
nets: &npnr::Nets,
|
|
||||||
arcs: &[Arc],
|
arcs: &[Arc],
|
||||||
pips: &[npnr::PipId],
|
pips: &[npnr::PipId],
|
||||||
x_start: i32,
|
x_start: i32,
|
||||||
@ -98,7 +97,6 @@ pub fn find_partition_point(
|
|||||||
while x_diff != 0 {
|
while x_diff != 0 {
|
||||||
(ne, se, sw, nw, misc) = partition(
|
(ne, se, sw, nw, misc) = partition(
|
||||||
ctx,
|
ctx,
|
||||||
nets,
|
|
||||||
arcs,
|
arcs,
|
||||||
pips,
|
pips,
|
||||||
x,
|
x,
|
||||||
@ -143,7 +141,6 @@ pub fn find_partition_point(
|
|||||||
|
|
||||||
(ne, se, sw, nw, misc) = partition(
|
(ne, se, sw, nw, misc) = partition(
|
||||||
ctx,
|
ctx,
|
||||||
nets,
|
|
||||||
arcs,
|
arcs,
|
||||||
pips,
|
pips,
|
||||||
x,
|
x,
|
||||||
@ -207,9 +204,15 @@ fn split_line_over_y(line: (npnr::Loc, npnr::Loc), y_location: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A big thank you to @Spacecat-chan for fixing my broken and buggy partition code.
|
// A big thank you to @Spacecat-chan for fixing my broken and buggy partition code.
|
||||||
|
|
||||||
|
// SpaceCat~Chan:
|
||||||
|
/// ### Current State of the Partitioner:
|
||||||
|
/// after some annoying discoveries, it turns out that partitioning correctly requires ensuring much
|
||||||
|
/// more that just having each pip not be reused by different nets, it turns out we also need to care
|
||||||
|
/// about the source and sink wires, so this current partitioner is written only to produce a partition
|
||||||
|
/// result which is correct, without any care about speed or actual pathing optimality
|
||||||
fn partition<R: RangeBounds<i32>>(
|
fn partition<R: RangeBounds<i32>>(
|
||||||
ctx: &npnr::Context,
|
ctx: &npnr::Context,
|
||||||
nets: &npnr::Nets,
|
|
||||||
arcs: &[Arc],
|
arcs: &[Arc],
|
||||||
pips: &[npnr::PipId],
|
pips: &[npnr::PipId],
|
||||||
x: i32,
|
x: i32,
|
||||||
@ -559,6 +562,7 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
if middle.0 == x {
|
if middle.0 == x {
|
||||||
middle.0 = x + 1;
|
middle.0 = x + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pips = match (source_is_east, source_is_north) {
|
let pips = match (source_is_east, source_is_north) {
|
||||||
(true, false) => &pips_w_s,
|
(true, false) => &pips_w_s,
|
||||||
(false, false) => &pips_e_s,
|
(false, false) => &pips_e_s,
|
||||||
@ -606,6 +610,8 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
middle_vert.1.clamp(1, ctx.grid_dim_y() - 1),
|
middle_vert.1.clamp(1, ctx.grid_dim_y() - 1),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let horiz_happens_first = (middle_horiz.1 < y) == source_is_east;
|
||||||
|
|
||||||
// need to avoid the partition point
|
// need to avoid the partition point
|
||||||
if middle_horiz.1 == y || middle_vert.0 == x {
|
if middle_horiz.1 == y || middle_vert.0 == x {
|
||||||
if source_is_east != sink_is_north {
|
if source_is_east != sink_is_north {
|
||||||
@ -617,22 +623,29 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let pips = match (source_is_north, source_is_east) {
|
let pips = match (source_is_north, source_is_east, horiz_happens_first) {
|
||||||
(true, false) => &pips_s_w,
|
(true, false, true) => &pips_s_w,
|
||||||
(false, false) => &pips_n_w,
|
(false, false, true) => &pips_n_w,
|
||||||
(true, true) => &pips_s_e,
|
(true, true, true) => &pips_s_e,
|
||||||
(false, true) => &pips_n_e,
|
(false, true, true) => &pips_n_e,
|
||||||
|
(true, false, false) => &pips_s_e,
|
||||||
|
(false, false, false) => &pips_n_e,
|
||||||
|
(true, true, false) => &pips_s_w,
|
||||||
|
(false, true, false) => &pips_n_w,
|
||||||
};
|
};
|
||||||
|
|
||||||
let horiz_pip = find_best_pip(pips, arc, &congestion);
|
let horiz_pip = find_best_pip(pips, arc, &congestion);
|
||||||
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
let pips = match (source_is_east, source_is_north) {
|
let pips = match (source_is_east, source_is_north, horiz_happens_first) {
|
||||||
// horiz pip forced to happen first, so we are now on ther other side of the north/south border
|
(true, false, true) => &pips_w_n,
|
||||||
(true, false) => &pips_w_n,
|
(false, false, true) => &pips_e_n,
|
||||||
(false, false) => &pips_e_n,
|
(true, true, true) => &pips_w_s,
|
||||||
(true, true) => &pips_w_s,
|
(false, true, true) => &pips_e_s,
|
||||||
(false, true) => &pips_e_s,
|
(true, false, false) => &pips_w_s,
|
||||||
|
(false, false, false) => &pips_e_s,
|
||||||
|
(true, true, false) => &pips_w_n,
|
||||||
|
(false, true, false) => &pips_e_n,
|
||||||
};
|
};
|
||||||
|
|
||||||
let vert_pip = find_best_pip(pips, arc, &congestion);
|
let vert_pip = find_best_pip(pips, arc, &congestion);
|
||||||
@ -660,28 +673,43 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
overuse.insert(ctx.pip_dst_wire(vert_pip), 1);
|
overuse.insert(ctx.pip_dst_wire(vert_pip), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let horiz_loc: Coord = ctx.pip_location(horiz_pip).into();
|
let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = if horiz_happens_first {
|
||||||
let horiz_is_east = horiz_loc.is_east_of(&partition_coords);
|
|
||||||
let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = {
|
|
||||||
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);
|
||||||
(a, b, c)
|
(a, b, c)
|
||||||
|
} else {
|
||||||
|
let (a, b) = arc.split(ctx, vert_pip);
|
||||||
|
let (b, c) = b.split(ctx, horiz_pip);
|
||||||
|
(a, b, c)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (seg1, seg2, seg3) = match (source_is_north, source_is_east) {
|
let (seg1, seg2, seg3) =
|
||||||
(true, true) => {
|
match (source_is_north, source_is_east, horiz_happens_first) {
|
||||||
(Segment::Northeast, Segment::Southeast, Segment::Southwest)
|
(true, true, true) => {
|
||||||
}
|
(Segment::Northeast, Segment::Southeast, Segment::Southwest)
|
||||||
(true, false) => {
|
}
|
||||||
(Segment::Northwest, Segment::Southwest, Segment::Southeast)
|
(true, false, true) => {
|
||||||
}
|
(Segment::Northwest, Segment::Southwest, Segment::Southeast)
|
||||||
(false, true) => {
|
}
|
||||||
(Segment::Southeast, Segment::Northeast, Segment::Northwest)
|
(false, true, true) => {
|
||||||
}
|
(Segment::Southeast, Segment::Northeast, Segment::Northwest)
|
||||||
(false, false) => {
|
}
|
||||||
(Segment::Southwest, Segment::Northwest, Segment::Northeast)
|
(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),
|
||||||
@ -803,7 +831,6 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
|
|
||||||
pub fn find_partition_point_and_sanity_check(
|
pub fn find_partition_point_and_sanity_check(
|
||||||
ctx: &npnr::Context,
|
ctx: &npnr::Context,
|
||||||
nets: &npnr::Nets,
|
|
||||||
arcs: &[Arc],
|
arcs: &[Arc],
|
||||||
pips: &[npnr::PipId],
|
pips: &[npnr::PipId],
|
||||||
x_start: i32,
|
x_start: i32,
|
||||||
@ -812,7 +839,7 @@ pub fn find_partition_point_and_sanity_check(
|
|||||||
y_finish: i32,
|
y_finish: i32,
|
||||||
) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) {
|
) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) {
|
||||||
let (x_part, y_part, ne, se, sw, nw, misc) =
|
let (x_part, y_part, ne, se, sw, nw, misc) =
|
||||||
find_partition_point(ctx, nets, arcs, pips, x_start, x_finish, y_start, y_finish);
|
find_partition_point(ctx, arcs, pips, x_start, x_finish, y_start, y_finish);
|
||||||
|
|
||||||
let mut invalid_arcs_in_ne = 0;
|
let mut invalid_arcs_in_ne = 0;
|
||||||
let mut invalid_arcs_in_se = 0;
|
let mut invalid_arcs_in_se = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user