make pip selection cache

This commit is contained in:
SpaceCat-Chan 2022-12-03 03:45:22 +01:00 committed by Lofty
parent a1b9222bd2
commit 8fdb7c78c7
3 changed files with 87 additions and 41 deletions

View File

@ -184,6 +184,7 @@ fn route(ctx: &mut npnr::Context) -> bool {
ctx, ctx,
&partitionable_arcs[..], &partitionable_arcs[..],
pips, pips,
&nets,
0, 0,
ctx.grid_dim_x(), ctx.grid_dim_x(),
0, 0,

View File

@ -46,7 +46,7 @@ impl NetInfo {
} }
#[repr(transparent)] #[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct NetIndex(i32); pub struct NetIndex(i32);
#[repr(C)] #[repr(C)]

View File

@ -2,14 +2,17 @@ use std::{
cmp::Ordering, cmp::Ordering,
collections::HashMap, collections::HashMap,
ops::RangeBounds, ops::RangeBounds,
sync::{atomic::AtomicUsize, Mutex}, sync::{atomic::AtomicUsize, Mutex, RwLock},
}; };
use colored::Colorize; use colored::Colorize;
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle}; use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle};
use rayon::prelude::*; use rayon::prelude::*;
use crate::{npnr, route::Arc}; use crate::{
npnr::{self, NetIndex},
route::Arc,
};
pub enum Segment { pub enum Segment {
Northeast, Northeast,
@ -111,6 +114,7 @@ pub fn find_partition_point(
ctx: &npnr::Context, ctx: &npnr::Context,
arcs: &[Arc], arcs: &[Arc],
pips: &[npnr::PipId], pips: &[npnr::PipId],
nets: &npnr::Nets,
x_start: i32, x_start: i32,
x_finish: i32, x_finish: i32,
y_start: i32, y_start: i32,
@ -131,6 +135,7 @@ pub fn find_partition_point(
ctx, ctx,
arcs, arcs,
pips, pips,
nets,
x, x,
y, y,
x_start..=x_finish, x_start..=x_finish,
@ -175,6 +180,7 @@ pub fn find_partition_point(
ctx, ctx,
arcs, arcs,
pips, pips,
nets,
x, x,
y, y,
x_start..=x_finish, x_start..=x_finish,
@ -247,6 +253,7 @@ fn partition<R: RangeBounds<i32>>(
ctx: &npnr::Context, ctx: &npnr::Context,
arcs: &[Arc], arcs: &[Arc],
pips: &[npnr::PipId], pips: &[npnr::PipId],
nets: &npnr::Nets,
x: i32, x: i32,
y: i32, y: i32,
x_bounds: R, x_bounds: R,
@ -270,7 +277,7 @@ fn partition<R: RangeBounds<i32>>(
y_str.bold() y_str.bold()
); );
let pip_selector = PipSelector::new(ctx, pips, (x_bounds, y_bounds), (x, y).into()); let pip_selector = PipSelector::new(ctx, pips, (x_bounds, y_bounds), (x, y).into(), nets);
let mut explored_pips = AtomicUsize::new(0); let mut explored_pips = AtomicUsize::new(0);
@ -613,13 +620,14 @@ pub fn find_partition_point_and_sanity_check(
ctx: &npnr::Context, ctx: &npnr::Context,
arcs: &[Arc], arcs: &[Arc],
pips: &[npnr::PipId], pips: &[npnr::PipId],
nets: &npnr::Nets,
x_start: i32, x_start: i32,
x_finish: i32, x_finish: i32,
y_start: i32, y_start: i32,
y_finish: i32, y_finish: i32,
) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) { ) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) {
let (x_part, y_part, ne, se, sw, nw) = let (x_part, y_part, ne, se, sw, nw) =
find_partition_point(ctx, arcs, pips, x_start, x_finish, y_start, y_finish); find_partition_point(ctx, arcs, pips, nets, x_start, x_finish, y_start, y_finish);
let mut invalid_arcs_in_ne = 0; let mut invalid_arcs_in_ne = 0;
let mut invalid_arcs_in_se = 0; let mut invalid_arcs_in_se = 0;
@ -691,26 +699,21 @@ struct PipSelector {
used_pips: HashMap<npnr::PipId, Mutex<Option<npnr::NetIndex>>>, used_pips: HashMap<npnr::PipId, Mutex<Option<npnr::NetIndex>>>,
used_wires: HashMap<npnr::WireId, Mutex<Option<npnr::NetIndex>>>, used_wires: HashMap<npnr::WireId, Mutex<Option<npnr::NetIndex>>>,
// first direction: where is this pip going // how to derive index described in `find_pip_index`
// second direction: where is this pip located pips: [Vec<npnr::PipId>; 8],
pips_n_e: Vec<npnr::PipId>, pip_selection_cache: [HashMap<NetIndex, RwLock<Option<npnr::PipId>>>; 8],
pips_e_n: Vec<npnr::PipId>,
pips_s_e: Vec<npnr::PipId>,
pips_w_n: Vec<npnr::PipId>,
pips_n_w: Vec<npnr::PipId>,
pips_e_s: Vec<npnr::PipId>,
pips_s_w: Vec<npnr::PipId>,
pips_w_s: Vec<npnr::PipId>,
partition_loc: npnr::Loc, partition_loc: npnr::Loc,
} }
impl PipSelector { impl PipSelector {
/// explores the pips and creates a pip selector from the results
fn new<R: RangeBounds<i32>>( fn new<R: RangeBounds<i32>>(
ctx: &npnr::Context, ctx: &npnr::Context,
pips: &[npnr::PipId], pips: &[npnr::PipId],
bounds: (R, R), bounds: (R, R),
partition_point: npnr::Loc, partition_point: npnr::Loc,
nets: &npnr::Nets,
) -> Self { ) -> Self {
let mut pips_n_e = vec![]; let mut pips_n_e = vec![];
let mut pips_e_n = vec![]; let mut pips_e_n = vec![];
@ -877,17 +880,33 @@ impl PipSelector {
used_wires.insert(ctx.pip_dst_wire(*pip), Mutex::new(None)); used_wires.insert(ctx.pip_dst_wire(*pip), Mutex::new(None));
} }
let mut caches = [
HashMap::new(),
HashMap::new(),
HashMap::new(),
HashMap::new(),
HashMap::new(),
HashMap::new(),
HashMap::new(),
HashMap::new(),
];
let nets = nets.to_vec();
for cache in &mut caches {
for (_, net) in nets.iter() {
let net = unsafe { net.as_ref().unwrap() };
cache.insert(net.index(), RwLock::new(None));
}
}
PipSelector { PipSelector {
used_pips, used_pips,
used_wires, used_wires,
pips_n_e, pips: [
pips_e_n, pips_w_n, pips_w_s, pips_e_n, pips_e_s, pips_s_e, pips_s_w, pips_n_e, pips_n_w,
pips_s_e, ],
pips_w_n, pip_selection_cache: caches,
pips_n_w,
pips_e_s,
pips_s_w,
pips_w_s,
partition_loc: partition_point, partition_loc: partition_point,
} }
} }
@ -900,24 +919,19 @@ impl PipSelector {
coming_from: npnr::Loc, coming_from: npnr::Loc,
net: npnr::NetIndex, net: npnr::NetIndex,
) -> npnr::PipId { ) -> npnr::PipId {
let desired_coord: Coord = desired_pip_location.into(); let pip_index = self.find_pip_index(desired_pip_location, coming_from);
let from_coord: Coord = coming_from.into(); // adding a scope to avoid holding the lock for too long
let pips = match ( {
desired_coord.full_segment(&self.partition_loc.into()), let cache = self.pip_selection_cache[pip_index]
from_coord.is_north_of(&self.partition_loc.into()), .get(&net)
from_coord.is_east_of(&self.partition_loc.into()), .unwrap()
) { .read()
(FullSegment::North, _, true) => &self.pips_w_n, .unwrap();
(FullSegment::South, _, true) => &self.pips_w_s, if let Some(pip) = *cache {
(FullSegment::North, _, false) => &self.pips_e_n, return pip;
(FullSegment::South, _, false) => &self.pips_e_s, }
(FullSegment::East, true, _) => &self.pips_s_e, }
(FullSegment::West, true, _) => &self.pips_s_w, let pips = &self.pips[pip_index];
(FullSegment::East, false, _) => &self.pips_n_e,
(FullSegment::West, false, _) => &self.pips_n_w,
(FullSegment::Exact, _, _) => panic!("can't find pips on the partition point"),
_ => panic!("pip must be on partition boundaries somewhere"),
};
let selected_pip = pips let selected_pip = pips
.iter() .iter()
@ -958,6 +972,37 @@ impl PipSelector {
}) })
.expect("unable to find a pip"); .expect("unable to find a pip");
{
let mut cache = self.pip_selection_cache[pip_index]
.get(&net)
.unwrap()
.write()
.unwrap();
*cache = Some(*selected_pip);
}
*selected_pip *selected_pip
} }
/// takes in a desired pip location and where the arc is coming from and figures out which index to use in the `self.pips` array
fn find_pip_index(&self, desired_pip_location: npnr::Loc, coming_from: npnr::Loc) -> usize {
let desired_coord: Coord = desired_pip_location.into();
let from_coord: Coord = coming_from.into();
match (
desired_coord.full_segment(&self.partition_loc.into()),
from_coord.is_north_of(&self.partition_loc.into()),
from_coord.is_east_of(&self.partition_loc.into()),
) {
(FullSegment::North, _, true) => 0,
(FullSegment::South, _, true) => 1,
(FullSegment::North, _, false) => 2,
(FullSegment::South, _, false) => 3,
(FullSegment::East, true, _) => 4,
(FullSegment::West, true, _) => 5,
(FullSegment::East, false, _) => 6,
(FullSegment::West, false, _) => 7,
(FullSegment::Exact, _, _) => panic!("can't find pips on the partition point"),
_ => panic!("pip must be on partition boundaries somewhere"),
}
}
} }