awooter: significantly speed up partitioner
Co-authored-by: SpaceCat-Chan <49094338+SpaceCat-Chan@users.noreply.github.com>
This commit is contained in:
parent
90f0630e62
commit
9a9d4c9392
@ -169,8 +169,8 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
ctx.grid_dim_y(),
|
ctx.grid_dim_y(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let time = Instant::now() - start;
|
let time = format!("{:.2}", (Instant::now() - start).as_secs_f32());
|
||||||
log_info!("Partitioning took {:.2}s\n", time.as_secs_f32());
|
log_info!("Partitioning took {}s\n", time.bold());
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
@ -209,12 +209,8 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
);
|
);
|
||||||
router.route(ctx, &nets, &misc, &progress);
|
router.route(ctx, &nets, &misc, &progress);
|
||||||
|
|
||||||
let time = Instant::now() - start;
|
let time = format!("{:.2}", (Instant::now() - start).as_secs_f32());
|
||||||
|
log_info!("Routing took {}s\n", time.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));
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ impl PipId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct WireId(u64);
|
pub struct WireId(u64);
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ impl Context {
|
|||||||
|
|
||||||
pub fn name_of_wire(&self, wire: WireId) -> &CStr {
|
pub fn name_of_wire(&self, wire: WireId) -> &CStr {
|
||||||
static MUTEX: Mutex<()> = Mutex::new(());
|
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)) }
|
unsafe { CStr::from_ptr(npnr_context_name_of_wire(self, wire)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
cmp::Ordering,
|
||||||
|
collections::HashMap,
|
||||||
ops::RangeBounds,
|
ops::RangeBounds,
|
||||||
sync::{atomic::AtomicUsize, Mutex},
|
sync::{atomic::AtomicUsize, Mutex},
|
||||||
};
|
};
|
||||||
@ -416,52 +417,68 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut congestion = HashMap::new();
|
let mut used_pips: HashMap<npnr::PipId, Mutex<Option<npnr::NetIndex>>> = HashMap::new();
|
||||||
|
let mut used_wires: HashMap<npnr::WireId, Mutex<Option<npnr::NetIndex>>> = HashMap::new();
|
||||||
|
|
||||||
let used_pips = Mutex::new(HashMap::new());
|
used_pips.reserve(pips.len());
|
||||||
let used_sinks = Mutex::new(HashMap::new());
|
|
||||||
let used_sources = Mutex::new(HashMap::new());
|
|
||||||
|
|
||||||
let find_best_pip = |pips: &Vec<std::sync::Arc<(npnr::PipId, AtomicUsize)>>,
|
let selected_pips = pips_n_e
|
||||||
arc: &Arc,
|
.iter()
|
||||||
congestion: &HashMap<npnr::WireId, i32>| {
|
.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<std::sync::Arc<(npnr::PipId, AtomicUsize)>>, arc: &Arc| {
|
||||||
let (selected_pip, pip_uses) = pips
|
let (selected_pip, pip_uses) = pips
|
||||||
.iter()
|
.iter()
|
||||||
.map(|a| a.as_ref())
|
.map(|a| a.as_ref())
|
||||||
.find(|(pip, uses)| {
|
.find(|(pip, _uses)| {
|
||||||
let source = ctx.pip_src_wire(*pip);
|
let source = ctx.pip_src_wire(*pip);
|
||||||
let sink = ctx.pip_dst_wire(*pip);
|
let sink = ctx.pip_dst_wire(*pip);
|
||||||
let used_pips = used_pips.lock().unwrap();
|
|
||||||
let used_sinks = used_sinks.lock().unwrap();
|
let (mut source, mut sink) = match sink.cmp(&source) {
|
||||||
let used_sources = used_sources.lock().unwrap();
|
Ordering::Greater => {
|
||||||
if used_pips.get(pip).map(|v| *v != arc.net()).unwrap_or(false) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if used_sinks
|
if source.map(|net| net != arc.net()).unwrap_or(false) {
|
||||||
.get(&source)
|
|
||||||
.map(|v| *v != arc.net())
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if used_sources
|
if sink.map(|net| net != arc.net()).unwrap_or(false) {
|
||||||
.get(&sink)
|
|
||||||
.map(|v| *v != arc.net())
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*candidate = Some(arc.net());
|
||||||
|
*source = Some(arc.net());
|
||||||
|
*sink = Some(arc.net());
|
||||||
|
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
.expect("unable to find a pip");
|
.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);
|
pip_uses.fetch_add(1, std::sync::atomic::Ordering::Release);
|
||||||
*selected_pip
|
*selected_pip
|
||||||
};
|
};
|
||||||
@ -524,7 +541,7 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
(false, true) => &pips_n_e,
|
(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);
|
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
@ -570,7 +587,7 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
(false, true) => &pips_e_n,
|
(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);
|
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
@ -634,7 +651,7 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
(false, true, false) => &pips_n_w,
|
(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);
|
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
let pips = match (source_is_east, source_is_north, horiz_happens_first) {
|
let pips = match (source_is_east, source_is_north, horiz_happens_first) {
|
||||||
@ -648,7 +665,7 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
(false, true, false) => &pips_e_n,
|
(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);
|
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
use std::{
|
use std::collections::{BinaryHeap, HashMap};
|
||||||
collections::{BinaryHeap, HashMap},
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use indicatif::{ProgressBar, ProgressStyle, MultiProgress};
|
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
npnr::{self, NetIndex, PipId},
|
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));
|
let progress = progress.add(ProgressBar::new(arcs.len() as u64));
|
||||||
progress.set_style(
|
progress.set_style(
|
||||||
ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}")
|
ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}")
|
||||||
@ -169,7 +172,7 @@ impl Router {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string();
|
.to_string();
|
||||||
let verbose = false;
|
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() {
|
while let Some(source) = queue.pop() {
|
||||||
if source.wire == arc.sink_wire {
|
if source.wire == arc.sink_wire {
|
||||||
|
Loading…
Reference in New Issue
Block a user