awooter: retry partitioning if there are overused wires

This commit is contained in:
Lofty 2022-11-30 16:48:50 +00:00
parent bed9ae6c17
commit 25ca4cdc01

View File

@ -1,4 +1,4 @@
use std::{collections::{HashMap, HashSet}, ops::RangeBounds, sync::atomic::AtomicUsize}; use std::{collections::{HashMap, HashSet}, ops::RangeBounds, sync::{atomic::AtomicUsize, Mutex}};
use colored::Colorize; use colored::Colorize;
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle}; use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle};
@ -275,10 +275,12 @@ fn partition<R: RangeBounds<i32>>(
if loc.y == y { if loc.y == y {
// pip is on east-west border // pip is on east-west border
let (mut src_has_east, mut src_has_west) = (false, false); let src_has_east = src_name.contains('E');
let (mut dst_has_east, mut dst_has_west) = (false, false); let src_has_west = src_name.contains('W');
let dst_has_east = dst_name.contains('E');
let dst_has_west = dst_name.contains('W');
for src_pip in ctx.get_uphill_pips(ctx.pip_src_wire(pip)) { /*for src_pip in ctx.get_uphill_pips(ctx.pip_src_wire(pip)) {
let src_pip_coord: Coord = ctx.pip_location(src_pip).into(); let src_pip_coord: Coord = ctx.pip_location(src_pip).into();
if (src_pip_coord.x < x) == (loc.x < x) { if (src_pip_coord.x < x) == (loc.x < x) {
src_has_east |= src_pip_coord.is_east_of(&partition_coords); src_has_east |= src_pip_coord.is_east_of(&partition_coords);
@ -291,15 +293,15 @@ fn partition<R: RangeBounds<i32>>(
dst_has_east |= dst_pip_coord.is_east_of(&partition_coords); dst_has_east |= dst_pip_coord.is_east_of(&partition_coords);
dst_has_west |= dst_pip_coord.is_west_of(&partition_coords); dst_has_west |= dst_pip_coord.is_west_of(&partition_coords);
} }
} }*/
if src_has_east && dst_has_west { if dst_has_west {
west += 1; west += 1;
pips_w pips_w
.entry((loc.x, loc.y)) .entry((loc.x, loc.y))
.or_insert(vec![]) .or_insert(vec![])
.push(pip_arc.clone()); .push(pip_arc.clone());
} }
if src_has_west && dst_has_east { if dst_has_east {
east += 1; east += 1;
pips_e pips_e
.entry((loc.x, loc.y)) .entry((loc.x, loc.y))
@ -309,31 +311,19 @@ fn partition<R: RangeBounds<i32>>(
} else { } else {
// pip is on south-north border // pip is on south-north border
let (mut src_has_north, mut src_has_south) = (false, false); let src_has_north = src_name.contains('N');
let (mut dst_has_north, mut dst_has_south) = (false, false); let src_has_south = src_name.contains('S');
let dst_has_north = dst_name.contains('N');
let dst_has_south = dst_name.contains('S');
for src_pip in ctx.get_uphill_pips(ctx.pip_src_wire(pip)) { if dst_has_south {
let src_pip_coord: Coord = ctx.pip_location(src_pip).into();
if (src_pip_coord.y < y) == (loc.y < y) {
src_has_north |= src_pip_coord.is_north_of(&partition_coords);
src_has_south |= src_pip_coord.is_south_of(&partition_coords);
}
}
for dst_pip in ctx.get_downhill_pips(ctx.pip_dst_wire(pip)) {
let dst_pip_coord: Coord = ctx.pip_location(dst_pip).into();
if (dst_pip_coord.y < y) == (loc.y < y) {
dst_has_north |= dst_pip_coord.is_north_of(&partition_coords);
dst_has_south |= dst_pip_coord.is_south_of(&partition_coords);
}
}
if src_has_north && dst_has_south {
south += 1; south += 1;
pips_s pips_s
.entry((loc.x, loc.y)) .entry((loc.x, loc.y))
.or_insert(vec![]) .or_insert(vec![])
.push(pip_arc.clone()); .push(pip_arc.clone());
} }
if src_has_south && dst_has_north { if dst_has_north {
north += 1; north += 1;
pips_n pips_n
.entry((loc.x, loc.y)) .entry((loc.x, loc.y))
@ -352,13 +342,6 @@ fn partition<R: RangeBounds<i32>>(
log_info!(" {} are south-bound\n", south.to_string().bold()); log_info!(" {} are south-bound\n", south.to_string().bold());
log_info!(" {} are west-bound\n", west.to_string().bold()); log_info!(" {} are west-bound\n", west.to_string().bold());
let progress = ProgressBar::new(arcs.len() as u64);
progress.set_style(
ProgressStyle::with_template("[{elapsed}] [{bar:40.cyan/blue}] {msg:30!}")
.unwrap()
.progress_chars("━╸ "),
);
let is_special_case = |arc: &Arc| { let is_special_case = |arc: &Arc| {
let src_name = ctx.name_of_wire(arc.get_source_wire()).to_str().unwrap(); let src_name = ctx.name_of_wire(arc.get_source_wire()).to_str().unwrap();
let dst_name = ctx.name_of_wire(arc.get_sink_wire()).to_str().unwrap(); let dst_name = ctx.name_of_wire(arc.get_sink_wire()).to_str().unwrap();
@ -370,7 +353,9 @@ fn partition<R: RangeBounds<i32>>(
false false
}; };
let find_best_pip = |pips: &Vec<std::sync::Arc<(npnr::PipId, AtomicUsize)>>, arc: &Arc| { let mut congestion = HashMap::new();
let find_best_pip = |pips: &Vec<std::sync::Arc<(npnr::PipId, AtomicUsize)>>, arc: &Arc, congestion: &HashMap<npnr::WireId, i32>| {
let (selected_pip, pip_uses) = pips let (selected_pip, pip_uses) = pips
.iter() .iter()
.map(|a| a.as_ref()) .map(|a| a.as_ref())
@ -378,7 +363,8 @@ fn partition<R: RangeBounds<i32>>(
let src_to_pip = ctx.estimate_delay(arc.get_source_wire(), ctx.pip_src_wire(*pip)); let src_to_pip = ctx.estimate_delay(arc.get_source_wire(), ctx.pip_src_wire(*pip));
let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), arc.get_sink_wire()); let pip_to_snk = ctx.estimate_delay(ctx.pip_dst_wire(*pip), arc.get_sink_wire());
let uses = uses.load(std::sync::atomic::Ordering::Acquire); let uses = uses.load(std::sync::atomic::Ordering::Acquire);
(1000.0 * (src_to_pip + ((uses + 1) as f32) * pip_to_snk)) as u64 let congestion = *congestion.get(&arc.get_sink_wire()).unwrap_or(&0) as f32;
(1000.0 * (src_to_pip + ((uses + 1) as f32) * (pip_to_snk + congestion))) as u64
}) })
.unwrap(); .unwrap();
pip_uses.fetch_add(1, std::sync::atomic::Ordering::Release); pip_uses.fetch_add(1, std::sync::atomic::Ordering::Release);
@ -393,6 +379,20 @@ fn partition<R: RangeBounds<i32>>(
} }
} }
let mut overused_wires = 1;
while overused_wires > 0 {
let progress = ProgressBar::new(arcs.len() as u64);
progress.set_style(
ProgressStyle::with_template("[{elapsed}] [{bar:40.cyan/blue}] {msg:30!}")
.unwrap()
.progress_chars("━╸ "),
);
progress.set_message(format!("overused wires: {}", overused_wires));
let overuse = Mutex::new(HashMap::new());
let arcs = arcs let arcs = arcs
.into_par_iter() .into_par_iter()
.progress_with(progress) .progress_with(progress)
@ -427,7 +427,7 @@ fn partition<R: RangeBounds<i32>>(
false => pips_n.get(&middle).unwrap(), false => pips_n.get(&middle).unwrap(),
}; };
let selected_pip = find_best_pip(pips, arc); let selected_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);
if verbose { if verbose {
@ -439,6 +439,13 @@ fn partition<R: RangeBounds<i32>>(
); );
} }
let mut overuse = overuse.lock().unwrap();
if let Some(entry) = overuse.get_mut(&ctx.pip_dst_wire(selected_pip)) {
*entry += 1;
} else {
overuse.insert(ctx.pip_dst_wire(selected_pip), 1);
}
let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip); let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip);
let (seg1, seg2) = match (source_is_north, source_is_east) { let (seg1, seg2) = match (source_is_north, source_is_east) {
(true, true) => (Segment::Northeast, Segment::Southeast), (true, true) => (Segment::Northeast, Segment::Southeast),
@ -463,7 +470,7 @@ fn partition<R: RangeBounds<i32>>(
false => pips_e.get(&middle).unwrap(), false => pips_e.get(&middle).unwrap(),
}; };
let selected_pip = find_best_pip(pips, arc); let selected_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);
if verbose { if verbose {
@ -475,6 +482,13 @@ fn partition<R: RangeBounds<i32>>(
); );
} }
let mut overuse = overuse.lock().unwrap();
if let Some(entry) = overuse.get_mut(&ctx.pip_dst_wire(selected_pip)) {
*entry += 1;
} else {
overuse.insert(ctx.pip_dst_wire(selected_pip), 1);
}
let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip); let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip);
let (seg1, seg2) = match (source_is_north, source_is_east) { let (seg1, seg2) = match (source_is_north, source_is_east) {
(true, true) => (Segment::Northeast, Segment::Northwest), (true, true) => (Segment::Northeast, Segment::Northwest),
@ -512,7 +526,7 @@ fn partition<R: RangeBounds<i32>>(
false => pips_n.get(&middle_horiz).unwrap(), false => pips_n.get(&middle_horiz).unwrap(),
}; };
let horiz_pip = find_best_pip(pips, arc); 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 { let pips = match source_is_east {
@ -520,7 +534,7 @@ fn partition<R: RangeBounds<i32>>(
false => pips_e.get(&middle_vert).unwrap(), false => pips_e.get(&middle_vert).unwrap(),
}; };
let vert_pip = find_best_pip(pips, arc); let vert_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);
if verbose { if verbose {
@ -533,6 +547,18 @@ fn partition<R: RangeBounds<i32>>(
); );
} }
let mut overuse = overuse.lock().unwrap();
if let Some(entry) = overuse.get_mut(&ctx.pip_dst_wire(horiz_pip)) {
*entry += 1;
} else {
overuse.insert(ctx.pip_dst_wire(horiz_pip), 1);
}
if let Some(entry) = overuse.get_mut(&ctx.pip_dst_wire(vert_pip)) {
*entry += 1;
} else {
overuse.insert(ctx.pip_dst_wire(vert_pip), 1);
}
let horiz_loc: Coord = ctx.pip_location(horiz_pip).into(); let horiz_loc: Coord = ctx.pip_location(horiz_pip).into();
let horiz_is_east = horiz_loc.is_east_of(&partition_coords); let horiz_is_east = horiz_loc.is_east_of(&partition_coords);
let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = if horiz_is_east == source_is_east { let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = if horiz_is_east == source_is_east {
@ -580,6 +606,8 @@ fn partition<R: RangeBounds<i32>>(
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let overuse = overuse.into_inner().unwrap();
for (segment, arc) in arcs { for (segment, arc) in arcs {
match segment { match segment {
Segment::Northeast => ne.push(arc), Segment::Northeast => ne.push(arc),
@ -589,6 +617,19 @@ fn partition<R: RangeBounds<i32>>(
} }
} }
overused_wires = 0;
for (wire, usage) in overuse {
if usage > 1 {
overused_wires += 1;
if let Some(entry) = congestion.get_mut(&wire) {
*entry += usage;
} else {
congestion.insert(wire, usage);
}
}
}
}
log_info!( log_info!(
" {} pips explored\n", " {} pips explored\n",
explored_pips.get_mut().to_string().bold() explored_pips.get_mut().to_string().bold()