diff --git a/common/route/awooter/rust/src/lib.rs b/common/route/awooter/rust/src/lib.rs index 32f9413e..03f89076 100644 --- a/common/route/awooter/rust/src/lib.rs +++ b/common/route/awooter/rust/src/lib.rs @@ -1,4 +1,8 @@ -use std::{collections::HashMap, ptr::NonNull, sync::{atomic::AtomicUsize, Mutex}}; +use std::{ + collections::HashMap, + ptr::NonNull, + sync::{atomic::AtomicUsize, Mutex}, +}; use colored::Colorize; use indicatif::{ProgressBar, ProgressStyle}; @@ -113,7 +117,6 @@ fn find_partition_point( (x, y, ne, se, sw, nw) } - /// finds the y location a line would be split at if you split it at a certain x location /// /// the function assumes the line goes on forever in both directions, and it truncates the actual coordinate @@ -158,7 +161,6 @@ enum Segment { Northwest, } - // A big thank you to @Spacecat-chan for fixing my broken and buggy partition code. fn partition_nets( ctx: &npnr::Context, @@ -193,7 +195,7 @@ fn partition_nets( // wrong direction. // // Possibly fixed? I need to double-check. - + let mut candidates = 0; let mut north = 0; let mut east = 0; @@ -214,46 +216,49 @@ fn partition_nets( if dir.x < 0 { north += 1; pips_n - .entry((loc.x, loc.y)) - .and_modify(|pip_list: &mut Vec<(npnr::PipId, Vec)>| { - pip_list.push((pip, Vec::new())) - }) - .or_insert_with(|| vec![(pip, Vec::new())]); + .entry((loc.x, loc.y)) + .and_modify(|pip_list: &mut Vec<(npnr::PipId, Vec)>| { + pip_list.push((pip, Vec::new())) + }) + .or_insert_with(|| vec![(pip, Vec::new())]); } if dir.x > 0 { south += 1; pips_s - .entry((loc.x, loc.y)) - .and_modify(|pip_list: &mut Vec<(npnr::PipId, Vec)>| { - pip_list.push((pip, Vec::new())) - }) - .or_insert_with(|| vec![(pip, Vec::new())]); + .entry((loc.x, loc.y)) + .and_modify(|pip_list: &mut Vec<(npnr::PipId, Vec)>| { + pip_list.push((pip, Vec::new())) + }) + .or_insert_with(|| vec![(pip, Vec::new())]); } if dir.y < 0 { east += 1; pips_e - .entry((loc.x, loc.y)) - .and_modify(|pip_list: &mut Vec<(npnr::PipId, Vec)>| { - pip_list.push((pip, Vec::new())) - }) - .or_insert_with(|| vec![(pip, Vec::new())]); + .entry((loc.x, loc.y)) + .and_modify(|pip_list: &mut Vec<(npnr::PipId, Vec)>| { + pip_list.push((pip, Vec::new())) + }) + .or_insert_with(|| vec![(pip, Vec::new())]); } if dir.y > 0 { west += 1; pips_w - .entry((loc.x, loc.y)) - .and_modify(|pip_list: &mut Vec<(npnr::PipId, Vec)>| { - pip_list.push((pip, Vec::new())) - }) - .or_insert_with(|| vec![(pip, Vec::new())]); + .entry((loc.x, loc.y)) + .and_modify(|pip_list: &mut Vec<(npnr::PipId, Vec)>| { + pip_list.push((pip, Vec::new())) + }) + .or_insert_with(|| vec![(pip, Vec::new())]); } } } - log_info!(" Out of {} candidate pips:\n", candidates.to_string().bold()); + log_info!( + " Out of {} candidate pips:\n", + candidates.to_string().bold() + ); log_info!(" {} are north-bound\n", north.to_string().bold()); log_info!(" {} are east-bound\n", east.to_string().bold()); log_info!(" {} are south-bound\n", south.to_string().bold()); @@ -304,167 +309,195 @@ fn partition_nets( // but doing so gives lifetime errors, and you can't describe // lifetimes in a closure, as far as I can tell. - let arcs = nets.users_by_name(*name).unwrap().iter().flat_map(|sink| { - let sink = unsafe { sink.as_ref().unwrap() }; - ctx.sink_wires(net, sink).into_iter().map(move |sink_wire| (sink, sink_wire)) - }).flat_map(|(sink, sink_wire)| { - let sink_loc = sink.cell().unwrap().location(); - let sink_is_north = sink_loc.x < x; - let sink_is_east = sink_loc.y < y; - if source_is_north == sink_is_north && source_is_east == sink_is_east { - let arc = ((source.x, source.y), (sink_loc.x, sink_loc.y)); - let seg = match (source_is_north, source_is_east) { - (true, true) => Segment::Northeast, - (true, false) => Segment::Northwest, - (false, true) => Segment::Southeast, - (false, false) => Segment::Southwest, - }; - vec![(seg, arc)] - } else if source_is_north != sink_is_north && source_is_east == sink_is_east { - let middle = (x, (source.y + sink_loc.y) / 2); - let mut pips_s = pips_s.lock().unwrap(); - let mut pips_n = pips_n.lock().unwrap(); - let pips = match source_is_north { - true => pips_s.get_mut(&middle).unwrap(), - false => pips_n.get_mut(&middle).unwrap(), - }; - - let (selected_pip, pip_uses) = pips - .iter_mut() - .min_by_key(|(pip, uses)| { - let src_to_pip = - ctx.estimate_delay(source_wire, ctx.pip_src_wire(*pip)); - let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), sink_wire); - let uses = uses.len() - (uses.contains(name) as usize); - (1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 - }) - .unwrap(); - pip_uses.push(*name); - let selected_pip = *selected_pip; - explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); - explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); - - let pip_loc = ctx.pip_location(selected_pip); - let src_to_pip = ((source.x, source.y), (pip_loc.x, pip_loc.y)); - let pip_to_dst = ((pip_loc.x, pip_loc.y), (sink_loc.x, sink_loc.y)); - let (seg1, seg2) = match (source_is_north, source_is_east) { - (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::SeqCst); - vec![(seg1, src_to_pip), (seg2, pip_to_dst)] - } else if source_is_north == sink_is_north && source_is_east != sink_is_east { - let middle = ((source.x + sink_loc.x) / 2, y); - let mut pips_e = pips_e.lock().unwrap(); - let mut pips_w = pips_w.lock().unwrap(); - let pips = match source_is_east { - true => pips_w.get_mut(&middle).unwrap(), - false => pips_e.get_mut(&middle).unwrap(), - }; - - let (selected_pip, pip_uses) = pips - .iter_mut() - .min_by_key(|(pip, uses)| { - let src_to_pip = - ctx.estimate_delay(source_wire, ctx.pip_src_wire(*pip)); - let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), sink_wire); - let uses = uses.len() - (uses.contains(name) as usize); - (1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 - }) - .unwrap(); - pip_uses.push(*name); - let selected_pip = *selected_pip; - explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); - - let pip_loc = ctx.pip_location(selected_pip); - let src_to_pip = ((source.x, source.y), (pip_loc.x, pip_loc.y)); - let pip_to_dst = ((pip_loc.x, pip_loc.y), (sink_loc.x, sink_loc.y)); - let (seg1, seg2) = match (source_is_north, source_is_east) { - (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::SeqCst); - vec![(seg1, src_to_pip), (seg2, pip_to_dst)] - } else { - let middle = (x, split_line_over_x((source, sink_loc), x)); - let mut pips_e = pips_e.lock().unwrap(); - let mut pips_w = pips_w.lock().unwrap(); - let pips = match source_is_east { - true => pips_w.get_mut(&middle).unwrap(), - false => pips_e.get_mut(&middle).unwrap(), - }; - - let (horiz_pip, pip_uses) = pips - .iter_mut() - .min_by_key(|(pip, uses)| { - let src_to_pip = - ctx.estimate_delay(source_wire, ctx.pip_src_wire(*pip)); - let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), sink_wire); - let uses = uses.len() - (uses.contains(name) as usize); - (1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 - }) - .unwrap(); - pip_uses.push(*name); - let horiz_pip = *horiz_pip; - explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); - - let middle = (split_line_over_y((source, sink_loc), y), y); - let mut pips_s = pips_s.lock().unwrap(); - let mut pips_n = pips_n.lock().unwrap(); - let pips = match source_is_north { - true => pips_s.get_mut(&middle).unwrap(), - false => pips_n.get_mut(&middle).unwrap(), - }; - - let (vert_pip, pip_uses) = pips - .iter_mut() - .min_by_key(|(pip, uses)| { - let src_to_pip = - ctx.estimate_delay(source_wire, ctx.pip_src_wire(*pip)); - let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), sink_wire); - let uses = uses.len() - (uses.contains(name) as usize); - (1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 - }) - .unwrap(); - pip_uses.push(*name); - let vert_pip = *vert_pip; - explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); - - let horiz_loc = ctx.pip_location(horiz_pip); - let horiz_is_east = horiz_loc.y < y; - let vert_loc = ctx.pip_location(vert_pip); - let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = - if horiz_is_east == source_is_east { - ( - ((source.x, source.y), (horiz_loc.x, horiz_loc.y)), - ((horiz_loc.x, horiz_loc.y), (vert_loc.x, vert_loc.y)), - ((vert_loc.x, vert_loc.y), (sink_loc.x, sink_loc.y)), - ) - } else { - ( - ((source.x, source.y), (vert_loc.x, vert_loc.y)), - ((vert_loc.x, vert_loc.y), (horiz_loc.x, horiz_loc.y)), - ((horiz_loc.x, horiz_loc.y), (sink_loc.x, sink_loc.y)), - ) + let arcs = nets + .users_by_name(*name) + .unwrap() + .iter() + .flat_map(|sink| { + let sink = unsafe { sink.as_ref().unwrap() }; + ctx.sink_wires(net, sink) + .into_iter() + .map(move |sink_wire| (sink, sink_wire)) + }) + .flat_map(|(sink, sink_wire)| { + let sink_loc = sink.cell().unwrap().location(); + let sink_is_north = sink_loc.x < x; + let sink_is_east = sink_loc.y < y; + if source_is_north == sink_is_north && source_is_east == sink_is_east { + let arc = ((source.x, source.y), (sink_loc.x, sink_loc.y)); + let seg = match (source_is_north, source_is_east) { + (true, true) => Segment::Northeast, + (true, false) => Segment::Northwest, + (false, true) => Segment::Southeast, + (false, false) => Segment::Southwest, }; - let (seg1, seg2, seg3) = match (source_is_north, source_is_east, horiz_is_east) { - (true, true, true) => (Segment::Northeast, Segment::Southeast, Segment::Southwest), - (true, true, false) => (Segment::Northeast, Segment::Northwest, Segment::Southwest), - (true, false, true) => (Segment::Northwest, Segment::Northeast, Segment::Southeast), - (true, false, false) => (Segment::Northwest, Segment::Southwest, Segment::Southeast), - (false, true, true) => (Segment::Southeast, Segment::Northeast, Segment::Northwest), - (false, true, false) => (Segment::Southeast, Segment::Southwest, Segment::Northwest), - (false, false, true) => (Segment::Southwest, Segment::Southeast, Segment::Northeast), - (false, false, false) => (Segment::Southwest, Segment::Northwest, Segment::Northeast), - }; - part_diag.fetch_add(1, std::sync::atomic::Ordering::SeqCst); - vec![(seg1, src_to_mid1), (seg2, mid1_to_mid2), (seg3, mid2_to_dst)] - } - }).collect::>(); + vec![(seg, arc)] + } else if source_is_north != sink_is_north && source_is_east == sink_is_east { + let middle = (x, (source.y + sink_loc.y) / 2); + let mut pips_s = pips_s.lock().unwrap(); + let mut pips_n = pips_n.lock().unwrap(); + let pips = match source_is_north { + true => pips_s.get_mut(&middle).unwrap(), + false => pips_n.get_mut(&middle).unwrap(), + }; + + let (selected_pip, pip_uses) = pips + .iter_mut() + .min_by_key(|(pip, uses)| { + let src_to_pip = + ctx.estimate_delay(source_wire, ctx.pip_src_wire(*pip)); + let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), sink_wire); + let uses = uses.len() - (uses.contains(name) as usize); + (1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 + }) + .unwrap(); + pip_uses.push(*name); + let selected_pip = *selected_pip; + explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); + + let pip_loc = ctx.pip_location(selected_pip); + let src_to_pip = ((source.x, source.y), (pip_loc.x, pip_loc.y)); + let pip_to_dst = ((pip_loc.x, pip_loc.y), (sink_loc.x, sink_loc.y)); + let (seg1, seg2) = match (source_is_north, source_is_east) { + (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::SeqCst); + vec![(seg1, src_to_pip), (seg2, pip_to_dst)] + } else if source_is_north == sink_is_north && source_is_east != sink_is_east { + let middle = ((source.x + sink_loc.x) / 2, y); + let mut pips_e = pips_e.lock().unwrap(); + let mut pips_w = pips_w.lock().unwrap(); + let pips = match source_is_east { + true => pips_w.get_mut(&middle).unwrap(), + false => pips_e.get_mut(&middle).unwrap(), + }; + + let (selected_pip, pip_uses) = pips + .iter_mut() + .min_by_key(|(pip, uses)| { + let src_to_pip = + ctx.estimate_delay(source_wire, ctx.pip_src_wire(*pip)); + let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), sink_wire); + let uses = uses.len() - (uses.contains(name) as usize); + (1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 + }) + .unwrap(); + pip_uses.push(*name); + let selected_pip = *selected_pip; + explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); + + let pip_loc = ctx.pip_location(selected_pip); + let src_to_pip = ((source.x, source.y), (pip_loc.x, pip_loc.y)); + let pip_to_dst = ((pip_loc.x, pip_loc.y), (sink_loc.x, sink_loc.y)); + let (seg1, seg2) = match (source_is_north, source_is_east) { + (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::SeqCst); + vec![(seg1, src_to_pip), (seg2, pip_to_dst)] + } else { + let middle = (x, split_line_over_x((source, sink_loc), x)); + let mut pips_e = pips_e.lock().unwrap(); + let mut pips_w = pips_w.lock().unwrap(); + let pips = match source_is_east { + true => pips_w.get_mut(&middle).unwrap(), + false => pips_e.get_mut(&middle).unwrap(), + }; + + let (horiz_pip, pip_uses) = pips + .iter_mut() + .min_by_key(|(pip, uses)| { + let src_to_pip = + ctx.estimate_delay(source_wire, ctx.pip_src_wire(*pip)); + let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), sink_wire); + let uses = uses.len() - (uses.contains(name) as usize); + (1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 + }) + .unwrap(); + pip_uses.push(*name); + let horiz_pip = *horiz_pip; + explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); + + let middle = (split_line_over_y((source, sink_loc), y), y); + let mut pips_s = pips_s.lock().unwrap(); + let mut pips_n = pips_n.lock().unwrap(); + let pips = match source_is_north { + true => pips_s.get_mut(&middle).unwrap(), + false => pips_n.get_mut(&middle).unwrap(), + }; + + let (vert_pip, pip_uses) = pips + .iter_mut() + .min_by_key(|(pip, uses)| { + let src_to_pip = + ctx.estimate_delay(source_wire, ctx.pip_src_wire(*pip)); + let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), sink_wire); + let uses = uses.len() - (uses.contains(name) as usize); + (1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 + }) + .unwrap(); + pip_uses.push(*name); + let vert_pip = *vert_pip; + explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::SeqCst); + + let horiz_loc = ctx.pip_location(horiz_pip); + let horiz_is_east = horiz_loc.y < y; + let vert_loc = ctx.pip_location(vert_pip); + let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = + if horiz_is_east == source_is_east { + ( + ((source.x, source.y), (horiz_loc.x, horiz_loc.y)), + ((horiz_loc.x, horiz_loc.y), (vert_loc.x, vert_loc.y)), + ((vert_loc.x, vert_loc.y), (sink_loc.x, sink_loc.y)), + ) + } else { + ( + ((source.x, source.y), (vert_loc.x, vert_loc.y)), + ((vert_loc.x, vert_loc.y), (horiz_loc.x, horiz_loc.y)), + ((horiz_loc.x, horiz_loc.y), (sink_loc.x, sink_loc.y)), + ) + }; + let (seg1, seg2, seg3) = match (source_is_north, source_is_east, horiz_is_east) + { + (true, true, true) => { + (Segment::Northeast, Segment::Southeast, Segment::Southwest) + } + (true, true, false) => { + (Segment::Northeast, Segment::Northwest, Segment::Southwest) + } + (true, false, true) => { + (Segment::Northwest, Segment::Northeast, Segment::Southeast) + } + (true, false, false) => { + (Segment::Northwest, Segment::Southwest, Segment::Southeast) + } + (false, true, true) => { + (Segment::Southeast, Segment::Northeast, Segment::Northwest) + } + (false, true, false) => { + (Segment::Southeast, Segment::Southwest, Segment::Northwest) + } + (false, false, true) => { + (Segment::Southwest, Segment::Southeast, Segment::Northeast) + } + (false, false, false) => { + (Segment::Southwest, Segment::Northwest, Segment::Northeast) + } + }; + part_diag.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + vec![ + (seg1, src_to_mid1), + (seg2, mid1_to_mid2), + (seg3, mid2_to_dst), + ] + } + }) + .collect::>(); for (segment, arc) in arcs { match segment { @@ -478,7 +511,10 @@ fn partition_nets( progress.finish_and_clear(); - log_info!(" {} pips explored\n", explored_pips.get_mut().to_string().bold()); + log_info!( + " {} pips explored\n", + explored_pips.get_mut().to_string().bold() + ); let north = ne.len() + nw.len(); let south = se.len() + sw.len(); @@ -696,7 +732,10 @@ fn route(ctx: &mut npnr::Context) -> bool { .into_iter() .all(|x| x == 0) { - log_info!("{}\n", "Found no arcs crossing partition boundaries.".green()); + log_info!( + "{}\n", + "Found no arcs crossing partition boundaries.".green() + ); } else { println!("{}", "found arcs crossing partition boundaries!".yellow()); println!("count in ne: {}", invalid_arcs_in_ne.to_string().bold());