From c13e840e41d16356a92cdfcca72d7f62c595cb0c Mon Sep 17 00:00:00 2001 From: Lofty Date: Fri, 2 Dec 2022 11:48:05 +0000 Subject: [PATCH] awooter: significantly speed up partitioner Co-authored-by: SpaceCat-Chan <49094338+SpaceCat-Chan@users.noreply.github.com> --- common/route/awooter/rust/src/lib.rs | 12 +-- common/route/awooter/rust/src/npnr.rs | 4 +- common/route/awooter/rust/src/partition.rs | 87 +++++++++++++--------- common/route/awooter/rust/src/route.rs | 17 +++-- 4 files changed, 68 insertions(+), 52 deletions(-) diff --git a/common/route/awooter/rust/src/lib.rs b/common/route/awooter/rust/src/lib.rs index 92fff66f..4e5d5319 100644 --- a/common/route/awooter/rust/src/lib.rs +++ b/common/route/awooter/rust/src/lib.rs @@ -169,8 +169,8 @@ fn route(ctx: &mut npnr::Context) -> bool { ctx.grid_dim_y(), ); - let time = Instant::now() - start; - log_info!("Partitioning took {:.2}s\n", time.as_secs_f32()); + let time = format!("{:.2}", (Instant::now() - start).as_secs_f32()); + log_info!("Partitioning took {}s\n", time.bold()); let start = Instant::now(); @@ -209,12 +209,8 @@ fn route(ctx: &mut npnr::Context) -> bool { ); 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() - ); + let time = format!("{:.2}", (Instant::now() - start).as_secs_f32()); + log_info!("Routing took {}s\n", time.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/npnr.rs b/common/route/awooter/rust/src/npnr.rs index 8f1d2104..49f51b66 100644 --- a/common/route/awooter/rust/src/npnr.rs +++ b/common/route/awooter/rust/src/npnr.rs @@ -99,7 +99,7 @@ impl PipId { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct WireId(u64); @@ -284,7 +284,7 @@ impl Context { pub fn name_of_wire(&self, wire: WireId) -> &CStr { static MUTEX: Mutex<()> = Mutex::new(()); - let lock = MUTEX.lock().unwrap(); + let _lock = MUTEX.lock().unwrap(); unsafe { CStr::from_ptr(npnr_context_name_of_wire(self, wire)) } } diff --git a/common/route/awooter/rust/src/partition.rs b/common/route/awooter/rust/src/partition.rs index c8d61833..7a9210e9 100644 --- a/common/route/awooter/rust/src/partition.rs +++ b/common/route/awooter/rust/src/partition.rs @@ -1,5 +1,6 @@ use std::{ - collections::{HashMap, HashSet}, + cmp::Ordering, + collections::HashMap, ops::RangeBounds, sync::{atomic::AtomicUsize, Mutex}, }; @@ -416,52 +417,68 @@ fn partition>( false }; - let mut congestion = HashMap::new(); + let mut used_pips: HashMap>> = HashMap::new(); + let mut used_wires: HashMap>> = HashMap::new(); - let used_pips = Mutex::new(HashMap::new()); - let used_sinks = Mutex::new(HashMap::new()); - let used_sources = Mutex::new(HashMap::new()); + used_pips.reserve(pips.len()); - let find_best_pip = |pips: &Vec>, - arc: &Arc, - congestion: &HashMap| { + let selected_pips = pips_n_e + .iter() + .chain(pips_e_n.iter()) + .chain(pips_e_s.iter()) + .chain(pips_s_e.iter()) + .chain(pips_s_w.iter()) + .chain(pips_w_s.iter()) + .chain(pips_w_n.iter()) + .chain(pips_n_w.iter()); + + for pip in selected_pips { + let (pip, _) = pip.as_ref(); + used_pips.insert(*pip, Mutex::new(None)); + used_wires.insert(ctx.pip_src_wire(*pip), Mutex::new(None)); + used_wires.insert(ctx.pip_dst_wire(*pip), Mutex::new(None)); + } + + let find_best_pip = |pips: &Vec>, arc: &Arc| { let (selected_pip, pip_uses) = pips .iter() .map(|a| a.as_ref()) - .find(|(pip, uses)| { + .find(|(pip, _uses)| { let source = ctx.pip_src_wire(*pip); let sink = ctx.pip_dst_wire(*pip); - let used_pips = used_pips.lock().unwrap(); - let used_sinks = used_sinks.lock().unwrap(); - let used_sources = used_sources.lock().unwrap(); - if used_pips.get(pip).map(|v| *v != arc.net()).unwrap_or(false) { + + let (mut source, mut sink) = match sink.cmp(&source) { + Ordering::Greater => { + let source = used_wires.get(&source).unwrap().lock().unwrap(); + let sink = used_wires.get(&sink).unwrap().lock().unwrap(); + (source, sink) + } + Ordering::Equal => return false, + Ordering::Less => { + let sink = used_wires.get(&sink).unwrap().lock().unwrap(); + let source = used_wires.get(&source).unwrap().lock().unwrap(); + (source, sink) + } + }; + + let mut candidate = used_pips.get(pip).unwrap().lock().unwrap(); + if candidate.map(|net| net != arc.net()).unwrap_or(false) { return false; } - if used_sinks - .get(&source) - .map(|v| *v != arc.net()) - .unwrap_or(false) - { + if source.map(|net| net != arc.net()).unwrap_or(false) { return false; } - if used_sources - .get(&sink) - .map(|v| *v != arc.net()) - .unwrap_or(false) - { + if sink.map(|net| net != arc.net()).unwrap_or(false) { return false; } + + *candidate = Some(arc.net()); + *source = Some(arc.net()); + *sink = Some(arc.net()); + true }) .expect("unable to find a pip"); - let source = ctx.pip_src_wire(*selected_pip); - let sink = ctx.pip_dst_wire(*selected_pip); - let mut used_pips = used_pips.lock().unwrap(); - let mut used_sinks = used_sinks.lock().unwrap(); - let mut used_sources = used_sources.lock().unwrap(); - used_pips.insert(*selected_pip, arc.net()); - used_sinks.insert(source, arc.net()); - used_sources.insert(sink, arc.net()); pip_uses.fetch_add(1, std::sync::atomic::Ordering::Release); *selected_pip }; @@ -524,7 +541,7 @@ fn partition>( (false, true) => &pips_n_e, }; - let selected_pip = find_best_pip(pips, arc, &congestion); + let selected_pip = find_best_pip(pips, arc); explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed); if verbose { @@ -570,7 +587,7 @@ fn partition>( (false, true) => &pips_e_n, }; - let selected_pip = find_best_pip(pips, arc, &congestion); + let selected_pip = find_best_pip(pips, arc); explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed); if verbose { @@ -634,7 +651,7 @@ fn partition>( (false, true, false) => &pips_n_w, }; - let horiz_pip = find_best_pip(pips, arc, &congestion); + let horiz_pip = find_best_pip(pips, arc); explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed); let pips = match (source_is_east, source_is_north, horiz_happens_first) { @@ -648,7 +665,7 @@ fn partition>( (false, true, false) => &pips_e_n, }; - let vert_pip = find_best_pip(pips, arc, &congestion); + let vert_pip = find_best_pip(pips, arc); explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed); if verbose { diff --git a/common/route/awooter/rust/src/route.rs b/common/route/awooter/rust/src/route.rs index b7065425..a1a0af71 100644 --- a/common/route/awooter/rust/src/route.rs +++ b/common/route/awooter/rust/src/route.rs @@ -1,9 +1,6 @@ -use std::{ - collections::{BinaryHeap, HashMap}, - time::Duration, -}; +use std::collections::{BinaryHeap, HashMap}; -use indicatif::{ProgressBar, ProgressStyle, MultiProgress}; +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use crate::{ npnr::{self, NetIndex, PipId}, @@ -126,7 +123,13 @@ impl Router { } } - pub fn route(&mut self, ctx: &npnr::Context, nets: &npnr::Nets, arcs: &[Arc], progress: &MultiProgress) { + pub fn route( + &mut self, + ctx: &npnr::Context, + nets: &npnr::Nets, + arcs: &[Arc], + progress: &MultiProgress, + ) { let progress = progress.add(ProgressBar::new(arcs.len() as u64)); progress.set_style( ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}") @@ -169,7 +172,7 @@ impl Router { .unwrap() .to_string(); let verbose = false; - //name == "decode_to_execute_IS_RS2_SIGNED_LUT4_D_1_Z_CCU2C_B1_S0_CCU2C_S0_3_B1"; + //name == "decode_to_execute_IS_RS2_SIGNED_LUT4_D_1_Z_CCU2C_B1_S0_CCU2C_S0_3_B1"; while let Some(source) = queue.pop() { if source.wire == arc.sink_wire {