nextpnr/common/route/awooter/rust/src/route.rs

277 lines
8.2 KiB
Rust
Raw Normal View History

use std::collections::{BinaryHeap, HashMap};
2022-11-29 05:15:04 +08:00
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
2022-11-28 03:27:33 +08:00
2022-11-28 03:47:16 +08:00
use crate::{
npnr::{self, NetIndex, PipId},
partition,
};
2022-11-27 23:28:59 +08:00
2022-11-28 03:47:16 +08:00
#[derive(Clone)]
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 {
cost: f32,
togo: f32,
wire: npnr::WireId,
}
impl QueuedWire {
pub fn new(cost: f32, togo: f32, wire: npnr::WireId) -> Self {
2022-11-28 03:47:16 +08:00
Self { cost, togo, wire }
2022-11-28 03:27:33 +08:00
}
}
impl PartialEq for QueuedWire {
fn eq(&self, other: &Self) -> bool {
self.cost == other.cost && self.togo == other.togo && self.wire == other.wire
}
}
impl Eq for QueuedWire {}
impl Ord for QueuedWire {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let me = self.cost + self.togo;
let other = other.cost + other.togo;
other.total_cmp(&me)
}
}
impl PartialOrd for QueuedWire {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
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,
bound_pip: HashMap<npnr::PipId, NetIndex>,
wire_driver: HashMap<npnr::WireId, npnr::PipId>,
}
impl Router {
pub fn new(box_ne: partition::Coord, box_sw: partition::Coord) -> Self {
Self {
box_ne,
box_sw,
bound_pip: HashMap::new(),
wire_driver: HashMap::new(),
}
}
pub fn route(
&mut self,
ctx: &npnr::Context,
nets: &npnr::Nets,
arcs: &[Arc],
progress: &MultiProgress,
) {
2022-11-30 09:20:14 +08:00
let progress = progress.add(ProgressBar::new(arcs.len() as u64));
2022-11-29 05:15:04 +08:00
progress.set_style(
ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}")
.unwrap()
.progress_chars("━╸ "),
);
2022-11-28 03:27:33 +08:00
for arc in arcs {
2022-11-29 05:15:04 +08:00
let net = unsafe { nets.net_from_index(arc.net).as_ref().unwrap() };
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-11-29 05:15:04 +08:00
if net.is_global() {
continue;
}
//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());
progress.inc(1);
progress.set_message(name);
self.route_arc(ctx, nets, arc);
2022-11-28 03:27:33 +08:00
}
2022-11-29 05:15:04 +08:00
progress.finish_and_clear()
2022-11-28 03:27:33 +08:00
}
2022-11-29 05:15:04 +08:00
fn route_arc(&mut self, ctx: &npnr::Context, nets: &npnr::Nets, arc: &Arc) {
2022-11-28 03:27:33 +08:00
let mut queue = BinaryHeap::new();
let mut visited = HashMap::new();
queue.push(QueuedWire::new(0.0, 0.0, arc.source_wire));
visited.insert(arc.source_wire, npnr::PipId::null());
2022-11-29 05:15:04 +08:00
let mut found_sink = false;
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-11-29 11:08:54 +08:00
let verbose = false;
//name == "decode_to_execute_IS_RS2_SIGNED_LUT4_D_1_Z_CCU2C_B1_S0_CCU2C_S0_3_B1";
2022-11-29 05:15:04 +08:00
2022-11-28 03:27:33 +08:00
while let Some(source) = queue.pop() {
if source.wire == arc.sink_wire {
2022-11-29 05:15:04 +08:00
found_sink = true;
2022-11-28 03:27:33 +08:00
break;
}
2022-11-29 05:15:04 +08:00
if verbose {
log_info!("{}:\n", ctx.name_of_wire(source.wire).to_str().unwrap());
}
2022-11-28 03:27:33 +08:00
for pip in ctx.get_downhill_pips(source.wire) {
2022-11-30 09:20:14 +08:00
let pip_loc = ctx.pip_location(pip);
2022-11-28 03:27:33 +08:00
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) {
continue;
}
if pip_coord.is_south_of(&self.box_sw) || pip_coord.is_west_of(&self.box_sw) {
continue;
2022-11-30 09:20:14 +08:00
}
2022-11-28 03:27:33 +08:00
/*
if (!ctx->checkPipAvailForNet(dh, net))
continue;
WireId next = ctx->getPipDstWire(dh);
int next_idx = wire_to_idx.at(next);
if (was_visited_fwd(next_idx)) {
// Don't expand the same node twice.
continue;
}
auto &nwd = flat_wires.at(next_idx);
if (nwd.unavailable)
continue;
// Reserved for another net
if (nwd.reserved_net != -1 && nwd.reserved_net != net->udata)
continue;
// Don't allow the same wire to be bound to the same net with a different driving pip
auto fnd_wire = nd.wires.find(next);
if (fnd_wire != nd.wires.end() && fnd_wire->second.first != dh)
continue;
if (!thread_test_wire(t, nwd))
continue; // thread safety issue
*/
let sink = ctx.pip_dst_wire(pip);
if visited.contains_key(&sink) {
continue;
}
2022-11-29 05:15:04 +08:00
/*let driver = self.wire_driver.get(&sink);
2022-11-28 03:27:33 +08:00
if let Some(&driver) = driver {
if driver != pip {
continue;
}
if *self.bound_pip.get(&driver).unwrap() != arc.net {
continue;
}
2022-11-29 05:15:04 +08:00
}*/
2022-11-28 03:27:33 +08:00
visited.insert(sink, pip);
2022-11-29 05:15:04 +08:00
if verbose {
log_info!(" {}\n", ctx.name_of_pip(pip).to_str().unwrap());
}
2022-11-28 03:47:16 +08:00
let delay =
source.cost + ctx.pip_delay(pip) + ctx.wire_delay(sink) + ctx.delay_epsilon();
2022-11-28 03:27:33 +08:00
let qw = QueuedWire::new(delay, ctx.estimate_delay(sink, arc.sink_wire), sink);
queue.push(qw);
}
}
2022-11-29 09:55:24 +08:00
assert!(
found_sink,
"didn't find sink wire for net {} between {} and {}",
name,
ctx.name_of_wire(arc.source_wire).to_str().unwrap(),
ctx.name_of_wire(arc.sink_wire).to_str().unwrap()
);
2022-11-29 05:15:04 +08:00
2022-11-28 03:27:33 +08:00
let mut wire = arc.sink_wire;
while wire != arc.source_wire {
2022-11-29 05:15:04 +08:00
/*if verbose {
println!("Wire: {}", ctx.name_of_wire(wire).to_str().unwrap());
}*/
2022-11-29 09:55:24 +08:00
let pip = *visited.get(&wire).unwrap_or_else(|| {
panic!(
"Expected wire {} to have driving pip",
ctx.name_of_wire(wire).to_str().unwrap()
)
});
2022-11-28 03:27:33 +08:00
self.bind_pip(pip, arc.net);
wire = ctx.pip_src_wire(pip);
}
}
fn bind_pip(&mut self, pip: PipId, net: NetIndex) {
2022-11-29 05:15:04 +08:00
//assert!(!self.bound_pip.contains_key(&pip));
2022-11-28 03:27:33 +08:00
self.bound_pip.insert(pip, net);
}
2022-11-28 00:26:17 +08:00
}