2022-12-11 23:12:01 +08:00
|
|
|
use std::{
|
|
|
|
collections::{BinaryHeap, HashMap, HashSet},
|
|
|
|
time::Instant,
|
|
|
|
};
|
2022-11-29 05:15:04 +08:00
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
use colored::Colorize;
|
2022-12-02 19:48:05 +08:00
|
|
|
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
|
2022-12-04 13:00:37 +08:00
|
|
|
use itertools::Itertools;
|
2022-11-28 03:27:33 +08:00
|
|
|
|
2022-11-28 03:47:16 +08:00
|
|
|
use crate::{
|
2022-12-03 14:26:15 +08:00
|
|
|
npnr::{self, NetIndex, PipId, WireId},
|
2022-11-28 03:47:16 +08:00
|
|
|
partition,
|
|
|
|
};
|
2022-11-27 23:28:59 +08:00
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
#[derive(Clone, Hash, PartialEq, Eq)]
|
2022-11-27 23:28:59 +08:00
|
|
|
pub struct Arc {
|
|
|
|
source_wire: npnr::WireId,
|
|
|
|
source_loc: npnr::Loc,
|
|
|
|
sink_wire: npnr::WireId,
|
|
|
|
sink_loc: npnr::Loc,
|
2022-11-28 03:27:33 +08:00
|
|
|
net: npnr::NetIndex,
|
2022-11-27 23:28:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Arc {
|
2022-11-28 03:47:16 +08:00
|
|
|
pub fn new(
|
|
|
|
source_wire: npnr::WireId,
|
|
|
|
source_loc: npnr::Loc,
|
|
|
|
sink_wire: npnr::WireId,
|
|
|
|
sink_loc: npnr::Loc,
|
|
|
|
net: NetIndex,
|
|
|
|
) -> Self {
|
2022-11-27 23:28:59 +08:00
|
|
|
Self {
|
2022-11-28 03:47:16 +08:00
|
|
|
source_wire,
|
|
|
|
source_loc,
|
|
|
|
sink_wire,
|
|
|
|
sink_loc,
|
|
|
|
net,
|
2022-11-27 23:28:59 +08:00
|
|
|
}
|
|
|
|
}
|
2022-11-28 00:26:17 +08:00
|
|
|
|
2022-11-28 03:47:16 +08:00
|
|
|
pub fn split(&self, ctx: &npnr::Context, pip: npnr::PipId) -> (Self, Self) {
|
2022-11-28 00:26:17 +08:00
|
|
|
let pip_src = ctx.pip_src_wire(pip);
|
|
|
|
let pip_dst = ctx.pip_dst_wire(pip);
|
2022-11-28 03:47:16 +08:00
|
|
|
(
|
|
|
|
Self {
|
|
|
|
source_wire: self.source_wire,
|
|
|
|
source_loc: self.source_loc,
|
|
|
|
sink_wire: pip_src,
|
|
|
|
sink_loc: ctx.pip_location(pip),
|
|
|
|
net: self.net,
|
|
|
|
},
|
|
|
|
Self {
|
|
|
|
source_wire: pip_dst,
|
|
|
|
source_loc: ctx.pip_location(pip),
|
|
|
|
sink_wire: self.sink_wire,
|
|
|
|
sink_loc: self.sink_loc,
|
|
|
|
net: self.net,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_source_loc(&self) -> npnr::Loc {
|
|
|
|
self.source_loc
|
|
|
|
}
|
|
|
|
pub fn get_sink_loc(&self) -> npnr::Loc {
|
|
|
|
self.sink_loc
|
|
|
|
}
|
|
|
|
pub fn get_source_wire(&self) -> npnr::WireId {
|
|
|
|
self.source_wire
|
|
|
|
}
|
|
|
|
pub fn get_sink_wire(&self) -> npnr::WireId {
|
|
|
|
self.sink_wire
|
2022-11-28 00:26:17 +08:00
|
|
|
}
|
2022-11-29 05:15:04 +08:00
|
|
|
pub fn net(&self) -> npnr::NetIndex {
|
|
|
|
self.net
|
|
|
|
}
|
2022-11-27 23:28:59 +08:00
|
|
|
}
|
|
|
|
|
2022-11-28 03:27:33 +08:00
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
struct QueuedWire {
|
2022-12-04 05:07:07 +08:00
|
|
|
delay: f32,
|
|
|
|
congest: f32,
|
2022-11-28 03:27:33 +08:00
|
|
|
togo: f32,
|
2022-12-04 10:24:34 +08:00
|
|
|
criticality: f32,
|
2022-11-28 03:27:33 +08:00
|
|
|
wire: npnr::WireId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl QueuedWire {
|
2022-12-04 10:24:34 +08:00
|
|
|
pub fn new(delay: f32, congest: f32, togo: f32, criticality: f32, wire: npnr::WireId) -> Self {
|
2022-12-04 15:15:43 +08:00
|
|
|
Self {
|
|
|
|
delay,
|
|
|
|
congest,
|
|
|
|
togo,
|
|
|
|
criticality,
|
|
|
|
wire,
|
|
|
|
}
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
2022-12-04 22:41:32 +08:00
|
|
|
|
|
|
|
fn score(&self) -> f32 {
|
|
|
|
(self.criticality * self.delay) + ((1.0 - self.criticality) * self.congest)
|
|
|
|
}
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for QueuedWire {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
2022-12-04 15:15:43 +08:00
|
|
|
self.delay == other.delay
|
|
|
|
&& self.congest == other.congest
|
|
|
|
&& self.togo == other.togo
|
|
|
|
&& self.wire == other.wire
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for QueuedWire {}
|
|
|
|
|
|
|
|
impl Ord for QueuedWire {
|
|
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
2022-12-04 22:41:32 +08:00
|
|
|
let me = self.score() + self.togo;
|
|
|
|
let other = other.score() + other.togo;
|
2022-11-28 03:27:33 +08:00
|
|
|
other.total_cmp(&me)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for QueuedWire {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-03 14:26:15 +08:00
|
|
|
struct PerNetData {
|
|
|
|
wires: HashMap<WireId, (PipId, u32)>,
|
2022-12-12 22:57:57 +08:00
|
|
|
done_sinks: HashSet<WireId>,
|
2022-12-03 14:26:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct PerWireData {
|
2022-12-04 05:07:07 +08:00
|
|
|
wire: WireId,
|
2022-12-03 14:26:15 +08:00
|
|
|
curr_cong: u32,
|
|
|
|
hist_cong: f32,
|
|
|
|
unavailable: bool,
|
|
|
|
reserved_net: Option<NetIndex>,
|
|
|
|
pip_fwd: PipId,
|
|
|
|
visited_fwd: bool,
|
2022-12-11 23:38:57 +08:00
|
|
|
pip_bwd: PipId,
|
|
|
|
visited_bwd: bool,
|
2022-12-03 14:26:15 +08:00
|
|
|
}
|
|
|
|
|
2022-11-28 00:26:17 +08:00
|
|
|
pub struct Router {
|
2022-11-28 03:27:33 +08:00
|
|
|
box_ne: partition::Coord,
|
|
|
|
box_sw: partition::Coord,
|
2022-12-04 13:00:37 +08:00
|
|
|
pressure: f32,
|
|
|
|
history: f32,
|
2022-12-03 14:26:15 +08:00
|
|
|
nets: Vec<PerNetData>,
|
|
|
|
wire_to_idx: HashMap<WireId, u32>,
|
|
|
|
flat_wires: Vec<PerWireData>,
|
|
|
|
dirty_wires: Vec<u32>,
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Router {
|
2022-12-04 15:15:43 +08:00
|
|
|
pub fn new(
|
|
|
|
box_ne: partition::Coord,
|
|
|
|
box_sw: partition::Coord,
|
|
|
|
pressure: f32,
|
|
|
|
history: f32,
|
|
|
|
) -> Self {
|
2022-11-28 03:27:33 +08:00
|
|
|
Self {
|
|
|
|
box_ne,
|
|
|
|
box_sw,
|
2022-12-04 13:00:37 +08:00
|
|
|
pressure,
|
|
|
|
history,
|
2022-12-03 14:26:15 +08:00
|
|
|
nets: Vec::new(),
|
|
|
|
wire_to_idx: HashMap::new(),
|
|
|
|
flat_wires: Vec::new(),
|
|
|
|
dirty_wires: Vec::new(),
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-02 19:48:05 +08:00
|
|
|
pub fn route(
|
|
|
|
&mut self,
|
|
|
|
ctx: &npnr::Context,
|
|
|
|
nets: &npnr::Nets,
|
2022-12-03 14:26:15 +08:00
|
|
|
wires: &[npnr::WireId],
|
2022-12-02 19:48:05 +08:00
|
|
|
arcs: &[Arc],
|
|
|
|
progress: &MultiProgress,
|
2022-12-04 05:07:07 +08:00
|
|
|
id: &str,
|
2022-12-02 19:48:05 +08:00
|
|
|
) {
|
2022-12-03 14:26:15 +08:00
|
|
|
for _ in 0..nets.len() {
|
2022-12-04 05:07:07 +08:00
|
|
|
self.nets.push(PerNetData {
|
|
|
|
wires: HashMap::new(),
|
2022-12-12 22:57:57 +08:00
|
|
|
done_sinks: HashSet::new(),
|
2022-12-04 05:07:07 +08:00
|
|
|
});
|
2022-12-03 14:26:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (idx, &wire) in wires.iter().enumerate() {
|
|
|
|
self.flat_wires.push(PerWireData {
|
|
|
|
wire,
|
|
|
|
curr_cong: 0,
|
|
|
|
hist_cong: 0.0,
|
|
|
|
unavailable: false,
|
|
|
|
reserved_net: None,
|
|
|
|
pip_fwd: PipId::null(),
|
2022-12-04 05:07:07 +08:00
|
|
|
visited_fwd: false,
|
2022-12-11 23:38:57 +08:00
|
|
|
pip_bwd: PipId::null(),
|
|
|
|
visited_bwd: false,
|
2022-12-03 14:26:15 +08:00
|
|
|
});
|
|
|
|
self.wire_to_idx.insert(wire, idx as u32);
|
|
|
|
}
|
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
let mut delay = HashMap::new();
|
|
|
|
|
|
|
|
for arc in arcs {
|
|
|
|
delay.insert(arc, 1.0_f32);
|
|
|
|
}
|
|
|
|
|
|
|
|
let start = Instant::now();
|
|
|
|
|
2022-12-04 10:24:34 +08:00
|
|
|
let mut max_delay = 1.0;
|
2022-12-07 16:36:00 +08:00
|
|
|
let mut least_overuse = usize::MAX;
|
|
|
|
let mut iters_since_improvement = 0;
|
|
|
|
|
|
|
|
let mut route_arcs = Vec::from_iter(arcs.iter());
|
2022-12-04 10:24:34 +08:00
|
|
|
|
2022-12-04 22:41:32 +08:00
|
|
|
let mut iterations = 0;
|
|
|
|
|
2022-12-04 05:07:07 +08:00
|
|
|
loop {
|
2022-12-04 22:41:32 +08:00
|
|
|
iterations += 1;
|
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
let progress = progress.add(ProgressBar::new(route_arcs.len() as u64));
|
2022-12-04 05:07:07 +08:00
|
|
|
progress.set_style(
|
|
|
|
ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}")
|
|
|
|
.unwrap()
|
|
|
|
.progress_chars("━╸ "),
|
|
|
|
);
|
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
for arc in route_arcs.iter().sorted_by(|&i, &j| {
|
|
|
|
(delay.get(j).unwrap() / max_delay).total_cmp(&(delay.get(i).unwrap() / max_delay))
|
2022-12-04 15:15:43 +08:00
|
|
|
}) {
|
2022-12-04 05:07:07 +08:00
|
|
|
let net = unsafe { nets.net_from_index(arc.net).as_ref().unwrap() };
|
2022-12-04 15:15:43 +08:00
|
|
|
let name = ctx.name_of(nets.name_from_index(arc.net)).to_str().unwrap();
|
2022-12-04 05:07:07 +08:00
|
|
|
|
|
|
|
if net.is_global() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-12-04 22:41:32 +08:00
|
|
|
//log_info!("{}\n", name);
|
|
|
|
//log_info!(" {} to {}\n", ctx.name_of_wire(arc.source_wire).to_str().unwrap(), ctx.name_of_wire(arc.sink_wire).to_str().unwrap());
|
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
let criticality = (delay.get(arc).unwrap() / max_delay).min(0.99).powf(2.5) + 0.1;
|
2022-12-04 05:07:07 +08:00
|
|
|
progress.inc(1);
|
2022-12-04 22:41:32 +08:00
|
|
|
progress.set_message(format!("{} @ {}: {}", id, iterations, name));
|
2022-12-07 16:36:00 +08:00
|
|
|
*delay.get_mut(arc).unwrap() = self.route_arc(ctx, nets, arc, criticality);
|
2022-12-04 05:07:07 +08:00
|
|
|
}
|
|
|
|
progress.finish_and_clear();
|
2022-11-29 05:15:04 +08:00
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
let mut overused = HashSet::new();
|
2022-12-04 05:07:07 +08:00
|
|
|
for wd in &mut self.flat_wires {
|
|
|
|
if wd.curr_cong > 1 {
|
2022-12-07 16:36:00 +08:00
|
|
|
overused.insert(wd.wire);
|
2022-12-04 13:00:37 +08:00
|
|
|
wd.hist_cong += (wd.curr_cong as f32) * self.history;
|
2022-12-07 16:36:00 +08:00
|
|
|
if false {
|
2022-12-04 22:41:32 +08:00
|
|
|
log_info!(
|
|
|
|
"wire {} has overuse {}\n",
|
|
|
|
ctx.name_of_wire(wd.wire).to_str().unwrap(),
|
|
|
|
wd.curr_cong
|
|
|
|
);
|
2022-12-07 16:36:00 +08:00
|
|
|
}
|
2022-12-04 05:07:07 +08:00
|
|
|
}
|
|
|
|
}
|
2022-11-29 05:15:04 +08:00
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
if overused.is_empty() {
|
|
|
|
let now = (Instant::now() - start).as_secs_f32();
|
2022-12-11 23:12:01 +08:00
|
|
|
progress.println(format!(
|
|
|
|
"{} @ {}: {} in {:.0}m{:.03}s",
|
|
|
|
id,
|
|
|
|
iterations,
|
|
|
|
"routing complete".green(),
|
|
|
|
now / 60.0,
|
|
|
|
now % 60.0
|
|
|
|
));
|
2022-12-04 05:07:07 +08:00
|
|
|
break;
|
2022-12-07 16:36:00 +08:00
|
|
|
} else if overused.len() < least_overuse {
|
|
|
|
least_overuse = overused.len();
|
|
|
|
iters_since_improvement = 0;
|
2022-12-11 23:12:01 +08:00
|
|
|
progress.println(format!(
|
|
|
|
"{} @ {}: {} wires overused {}",
|
|
|
|
id,
|
|
|
|
iterations,
|
|
|
|
overused.len(),
|
|
|
|
"(new best)".bold()
|
|
|
|
));
|
2022-12-07 16:36:00 +08:00
|
|
|
} else {
|
|
|
|
iters_since_improvement += 1;
|
2022-12-11 23:12:01 +08:00
|
|
|
progress.println(format!(
|
|
|
|
"{} @ {}: {} wires overused",
|
|
|
|
id,
|
|
|
|
iterations,
|
|
|
|
overused.len()
|
|
|
|
));
|
2022-11-29 05:15:04 +08:00
|
|
|
}
|
2022-12-04 05:07:07 +08:00
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
let mut next_arcs = Vec::new();
|
2022-12-04 10:24:34 +08:00
|
|
|
for arc in arcs {
|
2022-12-07 16:36:00 +08:00
|
|
|
for wire in self.nets[arc.net.into_inner() as usize].wires.keys() {
|
|
|
|
if overused.contains(wire) {
|
|
|
|
next_arcs.push(arc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for &arc in &route_arcs {
|
2022-12-04 10:24:34 +08:00
|
|
|
self.ripup_arc(ctx, arc);
|
|
|
|
}
|
2022-12-04 15:15:43 +08:00
|
|
|
for net in &mut self.nets {
|
|
|
|
net.done_sinks.clear();
|
|
|
|
}
|
2022-12-11 23:12:01 +08:00
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
if iters_since_improvement > 50 {
|
|
|
|
iters_since_improvement = 0;
|
|
|
|
least_overuse = usize::MAX;
|
2022-12-11 23:12:01 +08:00
|
|
|
progress.println(format!(
|
|
|
|
"{} @ {}: {}",
|
|
|
|
id,
|
|
|
|
iterations,
|
|
|
|
"bored; rerouting everything".bold()
|
|
|
|
));
|
2022-12-07 16:36:00 +08:00
|
|
|
route_arcs = Vec::from_iter(arcs.iter());
|
|
|
|
} else {
|
|
|
|
route_arcs = next_arcs;
|
|
|
|
}
|
2022-12-04 10:24:34 +08:00
|
|
|
|
2022-12-11 23:12:01 +08:00
|
|
|
max_delay = arcs
|
|
|
|
.iter()
|
|
|
|
.map(|arc| *delay.get(arc).unwrap())
|
|
|
|
.reduce(f32::max)
|
|
|
|
.unwrap();
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-04 15:15:43 +08:00
|
|
|
fn route_arc(
|
|
|
|
&mut self,
|
|
|
|
ctx: &npnr::Context,
|
|
|
|
nets: &npnr::Nets,
|
|
|
|
arc: &Arc,
|
|
|
|
criticality: f32,
|
|
|
|
) -> f32 {
|
2022-12-04 22:41:32 +08:00
|
|
|
if arc.source_wire == arc.sink_wire {
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
let mut fwd_queue = BinaryHeap::new();
|
|
|
|
fwd_queue.push(QueuedWire::new(
|
2022-12-04 15:15:43 +08:00
|
|
|
0.0,
|
|
|
|
0.0,
|
|
|
|
ctx.estimate_delay(arc.source_wire, arc.sink_wire),
|
|
|
|
criticality,
|
|
|
|
arc.source_wire,
|
|
|
|
));
|
2022-12-11 23:38:57 +08:00
|
|
|
let mut bwd_queue = BinaryHeap::new();
|
|
|
|
bwd_queue.push(QueuedWire::new(
|
|
|
|
0.0,
|
|
|
|
0.0,
|
|
|
|
ctx.estimate_delay(arc.source_wire, arc.sink_wire),
|
|
|
|
criticality,
|
|
|
|
arc.sink_wire,
|
|
|
|
));
|
2022-11-28 03:27:33 +08:00
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
let mut found_meeting_point = None;
|
2022-12-04 15:15:43 +08:00
|
|
|
let nd = &mut self.nets[arc.net().into_inner() as usize];
|
2022-11-29 05:15:04 +08:00
|
|
|
|
2022-11-29 09:55:24 +08:00
|
|
|
let name = ctx
|
|
|
|
.name_of(nets.name_from_index(arc.net))
|
|
|
|
.to_str()
|
|
|
|
.unwrap()
|
|
|
|
.to_string();
|
2022-12-07 16:36:00 +08:00
|
|
|
let verbose = ctx.verbose(); //false; //name == "soc0.processor.with_fpu.fpu_0.fpu_multiply_0.rin_CCU2C_S0_4$CCU2_FCI_INT";
|
2022-11-29 05:15:04 +08:00
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
let source_wire = *self.wire_to_idx.get(&arc.source_wire).unwrap();
|
|
|
|
let sink_wire = *self.wire_to_idx.get(&arc.sink_wire).unwrap();
|
|
|
|
|
|
|
|
self.flat_wires[source_wire as usize].visited_fwd = true;
|
|
|
|
self.flat_wires[sink_wire as usize].visited_bwd = true;
|
|
|
|
self.dirty_wires.push(source_wire);
|
|
|
|
self.dirty_wires.push(sink_wire);
|
|
|
|
|
2022-12-12 22:57:57 +08:00
|
|
|
if let Some(_) = nd.done_sinks.get(&arc.get_sink_wire()) {
|
2022-12-11 23:38:57 +08:00
|
|
|
found_meeting_point = Some(*self.wire_to_idx.get(&arc.sink_wire).unwrap());
|
2022-12-04 10:24:34 +08:00
|
|
|
|
2022-12-04 15:15:43 +08:00
|
|
|
let source = arc.get_source_wire();
|
|
|
|
let mut wire = arc.get_sink_wire();
|
|
|
|
while wire != source {
|
|
|
|
let nd = &mut self.nets[arc.net().into_inner() as usize];
|
|
|
|
let (driver, _) = nd.wires.get(&wire).unwrap();
|
|
|
|
let driver = *driver;
|
|
|
|
self.set_visited_fwd(self.wire_to_idx[&wire], driver);
|
|
|
|
wire = ctx.pip_src_wire(driver);
|
2022-11-29 05:15:04 +08:00
|
|
|
}
|
2022-12-04 15:15:43 +08:00
|
|
|
} else {
|
2022-12-11 23:38:57 +08:00
|
|
|
while found_meeting_point.is_none() {
|
|
|
|
if let Some(source) = fwd_queue.pop() {
|
|
|
|
if verbose {
|
|
|
|
let source_idx = *self.wire_to_idx.get(&source.wire).unwrap();
|
|
|
|
let source_cong = self.flat_wires[source_idx as usize].curr_cong;
|
|
|
|
log_info!(
|
|
|
|
"fwd: {} @ ({}, {}, {}) = {}\n",
|
|
|
|
ctx.name_of_wire(source.wire).to_str().unwrap(),
|
|
|
|
source.delay,
|
|
|
|
source.congest,
|
|
|
|
source.criticality,
|
|
|
|
source.score()
|
|
|
|
);
|
2022-12-04 15:15:43 +08:00
|
|
|
}
|
2022-12-11 23:38:57 +08:00
|
|
|
|
|
|
|
for pip in ctx.get_downhill_pips(source.wire) {
|
|
|
|
let pip_loc = ctx.pip_location(pip);
|
|
|
|
let pip_coord = partition::Coord::from(pip_loc);
|
|
|
|
if pip_coord.is_north_of(&self.box_ne) || pip_coord.is_east_of(&self.box_ne)
|
|
|
|
{
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" out-of-bounds (NE)\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if pip_coord.is_south_of(&self.box_sw) || pip_coord.is_west_of(&self.box_sw)
|
|
|
|
{
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" out-of-bounds (SW)\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if !ctx.pip_avail_for_net(pip, nets.net_from_index(arc.net())) {
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" pip unavailable for net\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let wire = ctx.pip_dst_wire(pip);
|
|
|
|
let sink = *self.wire_to_idx.get(&wire).unwrap();
|
|
|
|
if self.was_visited_fwd(sink) {
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" already visited\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let nd = &mut self.nets[arc.net().into_inner() as usize];
|
|
|
|
let nwd = &self.flat_wires[sink as usize];
|
|
|
|
if nwd.unavailable {
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" unavailable\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if let Some(net) = nwd.reserved_net && net != arc.net() {
|
2022-12-04 22:41:32 +08:00
|
|
|
/*if verbose {
|
|
|
|
log_info!(" reserved for other net\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
2022-12-03 14:26:15 +08:00
|
|
|
}
|
2022-12-11 23:38:57 +08:00
|
|
|
// Don't allow the same wire to be bound to the same net with a different driving pip
|
|
|
|
if let Some((found_pip, _)) = nd.wires.get(&wire) && *found_pip != pip {
|
2022-12-04 22:41:32 +08:00
|
|
|
/*if verbose {
|
|
|
|
log_info!(" driven by other pip\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
2022-12-03 14:26:15 +08:00
|
|
|
}
|
2022-11-28 03:27:33 +08:00
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
let node_delay =
|
|
|
|
ctx.pip_delay(pip) + ctx.wire_delay(wire) + ctx.delay_epsilon();
|
|
|
|
let sum_delay = source.delay + node_delay;
|
|
|
|
let congest = source.congest
|
|
|
|
+ (node_delay + nwd.hist_cong)
|
|
|
|
* (1.0 + (nwd.curr_cong as f32 * self.pressure));
|
|
|
|
|
|
|
|
let qw = QueuedWire::new(
|
|
|
|
sum_delay,
|
|
|
|
congest,
|
|
|
|
ctx.estimate_delay(wire, arc.sink_wire),
|
|
|
|
criticality,
|
|
|
|
wire,
|
|
|
|
);
|
|
|
|
|
|
|
|
self.set_visited_fwd(sink, pip);
|
|
|
|
|
|
|
|
if self.was_visited_bwd(sink) {
|
|
|
|
if verbose {
|
|
|
|
let source_cong = self.flat_wires[sink as usize].curr_cong;
|
|
|
|
log_info!(
|
|
|
|
"bwd: {} @ ({}, {}, {}) = {}\n",
|
|
|
|
ctx.name_of_wire(wire).to_str().unwrap(),
|
|
|
|
sum_delay,
|
|
|
|
congest,
|
|
|
|
criticality,
|
|
|
|
qw.score()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
found_meeting_point = Some(sink);
|
|
|
|
break;
|
2022-12-04 22:41:32 +08:00
|
|
|
}
|
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
fwd_queue.push(qw);
|
|
|
|
|
|
|
|
if false && verbose {
|
|
|
|
log_info!(
|
2022-12-12 22:57:57 +08:00
|
|
|
" bwd: {}: -> {} ({}, {}) = {}\n",
|
2022-12-11 23:38:57 +08:00
|
|
|
ctx.name_of_pip(pip).to_str().unwrap(),
|
|
|
|
ctx.name_of_wire(ctx.pip_dst_wire(pip)).to_str().unwrap(),
|
|
|
|
congest,
|
|
|
|
criticality,
|
|
|
|
qw.score()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if let Some(sink) = bwd_queue.pop() {
|
|
|
|
if verbose {
|
|
|
|
let sink_idx = *self.wire_to_idx.get(&sink.wire).unwrap();
|
|
|
|
let sink_cong = self.flat_wires[sink_idx as usize].curr_cong;
|
|
|
|
log_info!(
|
|
|
|
"bwd: {} @ ({}, {}, {}) = {}\n",
|
|
|
|
ctx.name_of_wire(sink.wire).to_str().unwrap(),
|
|
|
|
sink.delay,
|
|
|
|
sink.congest,
|
|
|
|
sink.criticality,
|
|
|
|
sink.score()
|
|
|
|
);
|
2022-12-04 22:41:32 +08:00
|
|
|
}
|
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
for pip in ctx.get_uphill_pips(sink.wire) {
|
|
|
|
let pip_loc = ctx.pip_location(pip);
|
|
|
|
let pip_coord = partition::Coord::from(pip_loc);
|
|
|
|
if pip_coord.is_north_of(&self.box_ne) || pip_coord.is_east_of(&self.box_ne)
|
|
|
|
{
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" out-of-bounds (NE)\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if pip_coord.is_south_of(&self.box_sw) || pip_coord.is_west_of(&self.box_sw)
|
|
|
|
{
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" out-of-bounds (SW)\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if !ctx.pip_avail_for_net(pip, nets.net_from_index(arc.net())) {
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" pip unavailable for net\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let wire = ctx.pip_src_wire(pip);
|
|
|
|
let source = *self.wire_to_idx.get(&wire).unwrap();
|
|
|
|
if self.was_visited_bwd(source) {
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" already visited\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let nd = &mut self.nets[arc.net().into_inner() as usize];
|
|
|
|
let nwd = &self.flat_wires[source as usize];
|
|
|
|
if nwd.unavailable {
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" unavailable\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if let Some(net) = nwd.reserved_net && net != arc.net() {
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" reserved for other net\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Don't allow the same wire to be bound to the same net with a different driving pip
|
|
|
|
if let Some((found_pip, _)) = nd.wires.get(&sink.wire) && *found_pip != pip {
|
|
|
|
/*if verbose {
|
|
|
|
log_info!(" driven by other pip\n");
|
|
|
|
}*/
|
|
|
|
continue;
|
|
|
|
}
|
2022-12-04 22:41:32 +08:00
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
let node_delay =
|
|
|
|
ctx.pip_delay(pip) + ctx.wire_delay(wire) + ctx.delay_epsilon();
|
|
|
|
let sum_delay = sink.delay + node_delay;
|
|
|
|
let congest = sink.congest
|
|
|
|
+ (node_delay + nwd.hist_cong)
|
|
|
|
* (1.0 + (nwd.curr_cong as f32 * self.pressure));
|
|
|
|
|
|
|
|
let qw = QueuedWire::new(
|
|
|
|
sum_delay,
|
|
|
|
congest,
|
|
|
|
ctx.estimate_delay(wire, arc.source_wire),
|
|
|
|
criticality,
|
|
|
|
wire,
|
|
|
|
);
|
|
|
|
|
|
|
|
self.set_visited_bwd(source, pip);
|
|
|
|
|
|
|
|
if self.was_visited_fwd(source) {
|
|
|
|
if verbose {
|
|
|
|
let source_cong = self.flat_wires[source as usize].curr_cong;
|
|
|
|
log_info!(
|
|
|
|
"bwd: {} @ ({}, {}, {}) = {}\n",
|
|
|
|
ctx.name_of_wire(wire).to_str().unwrap(),
|
|
|
|
sum_delay,
|
|
|
|
congest,
|
|
|
|
criticality,
|
|
|
|
qw.score()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
found_meeting_point = Some(source);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
bwd_queue.push(qw);
|
|
|
|
|
|
|
|
if false && verbose {
|
|
|
|
log_info!(
|
2022-12-12 22:57:57 +08:00
|
|
|
" bwd: {}: -> {} @ ({}, {}) = {}\n",
|
2022-12-11 23:38:57 +08:00
|
|
|
ctx.name_of_pip(pip).to_str().unwrap(),
|
|
|
|
ctx.name_of_wire(ctx.pip_dst_wire(pip)).to_str().unwrap(),
|
|
|
|
congest,
|
|
|
|
criticality,
|
|
|
|
qw.score()
|
|
|
|
);
|
|
|
|
}
|
2022-12-04 22:41:32 +08:00
|
|
|
}
|
2022-12-11 23:38:57 +08:00
|
|
|
} else {
|
|
|
|
// don't break when bwd goes bad, fwd was written by lofty, who knows all, this was written by dummy kbity
|
|
|
|
//break;
|
2022-12-04 15:15:43 +08:00
|
|
|
}
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 09:55:24 +08:00
|
|
|
assert!(
|
2022-12-11 23:38:57 +08:00
|
|
|
found_meeting_point.is_some(),
|
|
|
|
"didn't find sink wire for net {} between {} ({:?}) and {} ({:?})",
|
2022-11-29 09:55:24 +08:00
|
|
|
name,
|
|
|
|
ctx.name_of_wire(arc.source_wire).to_str().unwrap(),
|
2022-12-11 23:38:57 +08:00
|
|
|
arc.source_loc,
|
|
|
|
ctx.name_of_wire(arc.sink_wire).to_str().unwrap(),
|
|
|
|
arc.sink_loc,
|
2022-11-29 09:55:24 +08:00
|
|
|
);
|
2022-11-29 05:15:04 +08:00
|
|
|
|
2022-12-07 16:36:00 +08:00
|
|
|
if verbose {
|
|
|
|
println!(
|
|
|
|
"{} [label=\"{}\"]",
|
|
|
|
source_wire,
|
2022-12-11 23:12:01 +08:00
|
|
|
ctx.name_of_wire(arc.source_wire).to_str().unwrap(),
|
2022-12-07 16:36:00 +08:00
|
|
|
//self.flat_wires[wire as usize].curr_cong
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
let mut wire = found_meeting_point.unwrap();
|
|
|
|
if verbose {
|
|
|
|
println!(
|
|
|
|
"source: {} [label=\"{}\"]",
|
|
|
|
source_wire,
|
|
|
|
ctx.name_of_wire(self.flat_wires[source_wire as usize].wire)
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
|
|
|
//self.flat_wires[wire as usize].curr_cong
|
|
|
|
);
|
|
|
|
println!(
|
|
|
|
"sink: {} [label=\"{}\"]",
|
|
|
|
sink_wire,
|
|
|
|
ctx.name_of_wire(self.flat_wires[sink_wire as usize].wire)
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
|
|
|
//self.flat_wires[wire as usize].curr_cong
|
|
|
|
);
|
|
|
|
println!(
|
|
|
|
"middle: {} [label=\"{}\"]",
|
|
|
|
wire,
|
|
|
|
ctx.name_of_wire(self.flat_wires[wire as usize].wire)
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
|
|
|
//self.flat_wires[wire as usize].curr_cong
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-12-12 22:57:57 +08:00
|
|
|
let mut calculated_delay = 0.0;
|
|
|
|
|
2022-12-03 14:26:15 +08:00
|
|
|
while wire != source_wire {
|
|
|
|
if verbose {
|
2022-12-04 05:07:07 +08:00
|
|
|
println!(
|
2022-12-07 16:36:00 +08:00
|
|
|
"{} [label=\"{}\"]",
|
|
|
|
wire,
|
2022-12-04 05:07:07 +08:00
|
|
|
ctx.name_of_wire(self.flat_wires[wire as usize].wire)
|
|
|
|
.to_str()
|
2022-12-04 22:41:32 +08:00
|
|
|
.unwrap(),
|
2022-12-07 16:36:00 +08:00
|
|
|
//self.flat_wires[wire as usize].curr_cong
|
2022-12-04 05:07:07 +08:00
|
|
|
);
|
2022-12-03 14:26:15 +08:00
|
|
|
}
|
|
|
|
let pip = self.flat_wires[wire as usize].pip_fwd;
|
|
|
|
assert!(pip != PipId::null());
|
2022-12-07 16:36:00 +08:00
|
|
|
if verbose {
|
2022-12-11 23:12:01 +08:00
|
|
|
println!(
|
|
|
|
"{} -> {}",
|
|
|
|
*self.wire_to_idx.get(&ctx.pip_src_wire(pip)).unwrap(),
|
|
|
|
wire
|
|
|
|
);
|
2022-12-07 16:36:00 +08:00
|
|
|
}
|
2022-12-12 22:57:57 +08:00
|
|
|
|
|
|
|
let node_delay = ctx.pip_delay(pip)
|
|
|
|
+ ctx.wire_delay(self.flat_wires[wire as usize].wire)
|
|
|
|
+ ctx.delay_epsilon();
|
|
|
|
calculated_delay += node_delay;
|
|
|
|
|
2022-12-03 14:26:15 +08:00
|
|
|
self.bind_pip_internal(arc.net(), wire, pip);
|
|
|
|
wire = *self.wire_to_idx.get(&ctx.pip_src_wire(pip)).unwrap();
|
|
|
|
}
|
2022-12-11 23:38:57 +08:00
|
|
|
let mut wire = found_meeting_point.unwrap();
|
|
|
|
while wire != sink_wire {
|
|
|
|
let pip = self.flat_wires[wire as usize].pip_bwd;
|
|
|
|
assert!(pip != PipId::null());
|
|
|
|
// do note that the order is inverted from the fwd loop
|
|
|
|
wire = *self.wire_to_idx.get(&ctx.pip_dst_wire(pip)).unwrap();
|
2022-12-12 22:57:57 +08:00
|
|
|
|
|
|
|
let node_delay = ctx.pip_delay(pip)
|
|
|
|
+ ctx.wire_delay(self.flat_wires[wire as usize].wire)
|
|
|
|
+ ctx.delay_epsilon();
|
|
|
|
calculated_delay += node_delay;
|
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
self.bind_pip_internal(arc.net(), wire, pip);
|
|
|
|
}
|
2022-12-04 15:15:43 +08:00
|
|
|
let nd = &mut self.nets[arc.net().into_inner() as usize];
|
2022-12-12 22:57:57 +08:00
|
|
|
nd.done_sinks.insert(arc.get_sink_wire());
|
2022-12-03 14:26:15 +08:00
|
|
|
|
|
|
|
self.reset_wires();
|
2022-12-04 10:24:34 +08:00
|
|
|
|
2022-12-12 22:57:57 +08:00
|
|
|
calculated_delay
|
2022-12-03 14:26:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn was_visited_fwd(&self, wire: u32) -> bool {
|
|
|
|
self.flat_wires[wire as usize].visited_fwd
|
|
|
|
}
|
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
fn was_visited_bwd(&self, wire: u32) -> bool {
|
|
|
|
self.flat_wires[wire as usize].visited_bwd
|
|
|
|
}
|
|
|
|
|
2022-12-03 14:26:15 +08:00
|
|
|
fn set_visited_fwd(&mut self, wire: u32, pip: PipId) {
|
|
|
|
let wd = &mut self.flat_wires[wire as usize];
|
|
|
|
if !wd.visited_fwd {
|
|
|
|
self.dirty_wires.push(wire);
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
2022-12-03 14:26:15 +08:00
|
|
|
wd.pip_fwd = pip;
|
|
|
|
wd.visited_fwd = true;
|
2022-11-28 03:27:33 +08:00
|
|
|
}
|
|
|
|
|
2022-12-11 23:38:57 +08:00
|
|
|
fn set_visited_bwd(&mut self, wire: u32, pip: PipId) {
|
|
|
|
let wd = &mut self.flat_wires[wire as usize];
|
|
|
|
if !wd.visited_bwd {
|
|
|
|
self.dirty_wires.push(wire);
|
|
|
|
}
|
|
|
|
wd.pip_bwd = pip;
|
|
|
|
wd.visited_bwd = true;
|
|
|
|
}
|
|
|
|
|
2022-12-04 22:41:32 +08:00
|
|
|
fn bind_pip_internal(&mut self, netindex: NetIndex, wire: u32, pip: PipId) {
|
2022-12-03 14:26:15 +08:00
|
|
|
let wireid = self.flat_wires[wire as usize].wire;
|
2022-12-04 22:41:32 +08:00
|
|
|
let net = &mut self.nets[netindex.into_inner() as usize];
|
2022-12-03 14:26:15 +08:00
|
|
|
if let Some((bound_pip, usage)) = net.wires.get_mut(&wireid) {
|
|
|
|
assert!(*bound_pip == pip);
|
|
|
|
*usage += 1;
|
|
|
|
} else {
|
|
|
|
net.wires.insert(wireid, (pip, 1));
|
|
|
|
self.flat_wires[wire as usize].curr_cong += 1;
|
|
|
|
}
|
|
|
|
}
|
2022-12-04 05:07:07 +08:00
|
|
|
|
2022-12-04 10:24:34 +08:00
|
|
|
fn unbind_pip_internal(&mut self, net: NetIndex, wire: WireId) {
|
|
|
|
let net = net.into_inner() as usize;
|
|
|
|
let wireidx = *self.wire_to_idx.get(&wire).unwrap() as usize;
|
|
|
|
let (_pip, usage) = self.nets[net].wires.get_mut(&wire).unwrap();
|
|
|
|
*usage -= 1;
|
|
|
|
if *usage == 0 {
|
|
|
|
self.flat_wires[wireidx].curr_cong -= 1;
|
|
|
|
self.nets[net].wires.remove(&wire);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn ripup_arc(&mut self, ctx: &npnr::Context, arc: &Arc) {
|
|
|
|
let net = arc.net().into_inner() as usize;
|
|
|
|
let source_wire = arc.source_wire;
|
|
|
|
let mut wire = arc.sink_wire;
|
|
|
|
while wire != source_wire {
|
|
|
|
let pip = self.nets[net].wires.get(&wire).unwrap().0;
|
|
|
|
assert!(pip != PipId::null());
|
|
|
|
self.unbind_pip_internal(arc.net(), wire);
|
|
|
|
wire = ctx.pip_src_wire(pip);
|
2022-12-04 15:15:43 +08:00
|
|
|
}
|
2022-12-04 10:24:34 +08:00
|
|
|
}
|
|
|
|
|
2022-12-03 14:26:15 +08:00
|
|
|
fn reset_wires(&mut self) {
|
|
|
|
for &wire in &self.dirty_wires {
|
|
|
|
self.flat_wires[wire as usize].pip_fwd = PipId::null();
|
|
|
|
self.flat_wires[wire as usize].visited_fwd = false;
|
2022-12-11 23:38:57 +08:00
|
|
|
self.flat_wires[wire as usize].pip_bwd = PipId::null();
|
|
|
|
self.flat_wires[wire as usize].visited_bwd = false;
|
2022-12-03 14:26:15 +08:00
|
|
|
}
|
|
|
|
self.dirty_wires.clear();
|
|
|
|
}
|
2022-11-28 00:26:17 +08:00
|
|
|
}
|