From 90f0630e622d80ee1a4c92374f974d1de41a8486 Mon Sep 17 00:00:00 2001 From: SpaceCat-Chan <49094338+SpaceCat-Chan@users.noreply.github.com> Date: Thu, 1 Dec 2022 20:29:24 +0100 Subject: [PATCH] make slight improvement to partitioner --- common/route/awooter/rust/src/lib.rs | 31 +++++-- common/route/awooter/rust/src/partition.rs | 95 ++++++++++++++-------- 2 files changed, 85 insertions(+), 41 deletions(-) diff --git a/common/route/awooter/rust/src/lib.rs b/common/route/awooter/rust/src/lib.rs index 3ac282ac..92fff66f 100644 --- a/common/route/awooter/rust/src/lib.rs +++ b/common/route/awooter/rust/src/lib.rs @@ -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( ctx, - &nets, &arcs[..], pips, 0, @@ -180,10 +179,22 @@ fn route(ctx: &mut npnr::Context) -> bool { let progress = MultiProgress::new(); let partitions = [ - (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(0, y_part-1), Coord::new(x_part+1, ctx.grid_dim_y()), &nw) + (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(0, y_part - 1), + Coord::new(x_part + 1, ctx.grid_dim_y()), + &nw, + ), ]; 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"); - 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); 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)); diff --git a/common/route/awooter/rust/src/partition.rs b/common/route/awooter/rust/src/partition.rs index 7b561d0d..c8d61833 100644 --- a/common/route/awooter/rust/src/partition.rs +++ b/common/route/awooter/rust/src/partition.rs @@ -76,7 +76,6 @@ impl From for Coord { pub fn find_partition_point( ctx: &npnr::Context, - nets: &npnr::Nets, arcs: &[Arc], pips: &[npnr::PipId], x_start: i32, @@ -98,7 +97,6 @@ pub fn find_partition_point( while x_diff != 0 { (ne, se, sw, nw, misc) = partition( ctx, - nets, arcs, pips, x, @@ -143,7 +141,6 @@ pub fn find_partition_point( (ne, se, sw, nw, misc) = partition( ctx, - nets, arcs, pips, 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. + +// 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>( ctx: &npnr::Context, - nets: &npnr::Nets, arcs: &[Arc], pips: &[npnr::PipId], x: i32, @@ -559,6 +562,7 @@ fn partition>( if middle.0 == x { middle.0 = x + 1; } + let pips = match (source_is_east, source_is_north) { (true, false) => &pips_w_s, (false, false) => &pips_e_s, @@ -606,6 +610,8 @@ fn partition>( 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 if middle_horiz.1 == y || middle_vert.0 == x { if source_is_east != sink_is_north { @@ -617,22 +623,29 @@ fn partition>( } } - let pips = match (source_is_north, source_is_east) { - (true, false) => &pips_s_w, - (false, false) => &pips_n_w, - (true, true) => &pips_s_e, - (false, true) => &pips_n_e, + let pips = match (source_is_north, source_is_east, horiz_happens_first) { + (true, false, true) => &pips_s_w, + (false, false, true) => &pips_n_w, + (true, true, true) => &pips_s_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); explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed); - let pips = match (source_is_east, source_is_north) { - // horiz pip forced to happen first, so we are now on ther other side of the north/south border - (true, false) => &pips_w_n, - (false, false) => &pips_e_n, - (true, true) => &pips_w_s, - (false, true) => &pips_e_s, + let pips = match (source_is_east, source_is_north, horiz_happens_first) { + (true, false, true) => &pips_w_n, + (false, false, true) => &pips_e_n, + (true, true, true) => &pips_w_s, + (false, true, 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); @@ -660,28 +673,43 @@ fn partition>( overuse.insert(ctx.pip_dst_wire(vert_pip), 1); } - let horiz_loc: Coord = ctx.pip_location(horiz_pip).into(); - let horiz_is_east = horiz_loc.is_east_of(&partition_coords); - let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = { + let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = if horiz_happens_first { let (a, b) = arc.split(ctx, horiz_pip); let (b, c) = b.split(ctx, vert_pip); (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) { - (true, true) => { - (Segment::Northeast, Segment::Southeast, Segment::Southwest) - } - (true, false) => { - (Segment::Northwest, Segment::Southwest, Segment::Southeast) - } - (false, true) => { - (Segment::Southeast, Segment::Northeast, Segment::Northwest) - } - (false, false) => { - (Segment::Southwest, Segment::Northwest, Segment::Northeast) - } - }; + let (seg1, seg2, seg3) = + 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); vec![ (seg1, src_to_mid1), @@ -803,7 +831,6 @@ fn partition>( pub fn find_partition_point_and_sanity_check( ctx: &npnr::Context, - nets: &npnr::Nets, arcs: &[Arc], pips: &[npnr::PipId], x_start: i32, @@ -812,7 +839,7 @@ pub fn find_partition_point_and_sanity_check( y_finish: i32, ) -> (i32, i32, Vec, Vec, Vec, Vec, Vec) { 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_se = 0;