infrastructure for pre-routing
This commit is contained in:
parent
0bc945fbc3
commit
4b635cf68c
@ -1,6 +1,3 @@
|
|||||||
#![feature(c_unwind)]
|
|
||||||
#![feature(let_chains)]
|
|
||||||
|
|
||||||
use std::{ptr::NonNull, time::Instant};
|
use std::{ptr::NonNull, time::Instant};
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
@ -15,7 +12,7 @@ mod partition;
|
|||||||
mod route;
|
mod route;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C-unwind" fn npnr_router_awooter(
|
pub extern "C" fn npnr_router_awooter(
|
||||||
ctx: Option<NonNull<npnr::Context>>,
|
ctx: Option<NonNull<npnr::Context>>,
|
||||||
pressure: f32,
|
pressure: f32,
|
||||||
history: f32,
|
history: f32,
|
||||||
@ -59,18 +56,21 @@ fn extract_arcs_from_nets(ctx: &npnr::Context, nets: &npnr::Nets) -> Vec<route::
|
|||||||
let sink = sink_ref.cell().unwrap();
|
let sink = sink_ref.cell().unwrap();
|
||||||
let sink = sink.location();
|
let sink = sink.location();
|
||||||
for sink_wire in ctx.sink_wires(net, *sink_ref) {
|
for sink_wire in ctx.sink_wires(net, *sink_ref) {
|
||||||
arcs.push(route::Arc::new(
|
let arc = route::Arc::new(
|
||||||
source_wire,
|
source_wire,
|
||||||
Some(source),
|
Some(source),
|
||||||
sink_wire,
|
sink_wire,
|
||||||
Some(sink),
|
Some(sink),
|
||||||
net.index(),
|
net.index(),
|
||||||
nets.name_from_index(net.index()),
|
nets.name_from_index(net.index()),
|
||||||
));
|
);
|
||||||
|
if !arcs.contains(&arc) {
|
||||||
|
arcs.push(arc);
|
||||||
|
}
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
let source_wire = ctx.name_of_wire(source_wire).to_str().unwrap();
|
let source_wire = ctx.name_of_wire(source_wire);
|
||||||
let sink_wire = ctx.name_of_wire(sink_wire).to_str().unwrap();
|
let sink_wire = ctx.name_of_wire(sink_wire);
|
||||||
dbg!(source_wire, sink_wire, net.index().into_inner());
|
dbg!(source_wire, sink_wire, net.index().into_inner());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,11 +178,22 @@ fn route(ctx: &mut npnr::Context, pressure: f32, history: f32) -> bool {
|
|||||||
|
|
||||||
let arcs = extract_arcs_from_nets(ctx, &nets);
|
let arcs = extract_arcs_from_nets(ctx, &nets);
|
||||||
|
|
||||||
|
let router = route::Router::new(&nets, wires, pressure, history);
|
||||||
|
let progress = MultiProgress::new();
|
||||||
|
let mut thread = route::RouterThread::new(
|
||||||
|
Coord::new(0, 0),
|
||||||
|
Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()),
|
||||||
|
&arcs,
|
||||||
|
"pre-routing",
|
||||||
|
&progress
|
||||||
|
);
|
||||||
|
let arcs = router.find_general_routing(ctx, &nets, &mut thread);
|
||||||
|
|
||||||
let mut special_arcs = vec![];
|
let mut special_arcs = vec![];
|
||||||
let mut partitionable_arcs = Vec::with_capacity(arcs.len());
|
let mut partitionable_arcs = Vec::with_capacity(arcs.len());
|
||||||
for arc in arcs {
|
for arc in arcs {
|
||||||
let src_name = ctx.name_of_wire(arc.source_wire()).to_str().unwrap();
|
let src_name = ctx.name_of_wire(arc.source_wire());
|
||||||
let dst_name = ctx.name_of_wire(arc.sink_wire()).to_str().unwrap();
|
let dst_name = ctx.name_of_wire(arc.sink_wire());
|
||||||
|
|
||||||
if src_name.contains("FCO_SLICE")
|
if src_name.contains("FCO_SLICE")
|
||||||
|| src_name.contains("Q6_SLICE")
|
|| src_name.contains("Q6_SLICE")
|
||||||
@ -208,7 +219,7 @@ fn route(ctx: &mut npnr::Context, pressure: f32, history: f32) -> bool {
|
|||||||
String::from(""),
|
String::from(""),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
for _ in 0..2 {
|
for _ in 0..0 {
|
||||||
let mut new_partitions = Vec::with_capacity(partitions.len() * 4);
|
let mut new_partitions = Vec::with_capacity(partitions.len() * 4);
|
||||||
for (min, max, partition, name) in &partitions {
|
for (min, max, partition, name) in &partitions {
|
||||||
log_info!("partition {}:\n", name);
|
log_info!("partition {}:\n", name);
|
||||||
|
@ -302,10 +302,10 @@ impl Context {
|
|||||||
unsafe { CStr::from_ptr(npnr_context_name_of_pip(self, pip)) }
|
unsafe { CStr::from_ptr(npnr_context_name_of_pip(self, pip)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_of_wire(&self, wire: WireId) -> &CStr {
|
pub fn name_of_wire(&self, wire: WireId) -> &str {
|
||||||
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)) }.to_str().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verbose(&self) -> bool {
|
pub fn verbose(&self) -> bool {
|
||||||
@ -313,7 +313,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C-unwind" {
|
extern "C" {
|
||||||
pub fn npnr_log_info(format: *const c_char);
|
pub fn npnr_log_info(format: *const c_char);
|
||||||
pub fn npnr_log_error(format: *const c_char);
|
pub fn npnr_log_error(format: *const c_char);
|
||||||
|
|
||||||
|
@ -177,12 +177,12 @@ impl Coord {
|
|||||||
pub fn intersect(&self, other: &Self, axis: Axis, split_point: &Self) -> Self {
|
pub fn intersect(&self, other: &Self, axis: Axis, split_point: &Self) -> Self {
|
||||||
match axis {
|
match axis {
|
||||||
Axis::NorthSouth => Coord {
|
Axis::NorthSouth => Coord {
|
||||||
x: split_line_over_y(((*self).into(), (*other).into()), split_point.y),
|
x: split_line_over_y((*self, *other), split_point.y),
|
||||||
y: split_point.y,
|
y: split_point.y,
|
||||||
},
|
},
|
||||||
Axis::EastWest => Coord {
|
Axis::EastWest => Coord {
|
||||||
x: split_point.x,
|
x: split_point.x,
|
||||||
y: split_line_over_x(((*self).into(), (*other).into()), split_point.x),
|
y: split_line_over_x((*self, *other), split_point.x),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,10 +318,10 @@ pub fn find_partition_point(
|
|||||||
) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) {
|
) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) {
|
||||||
let mut x = ((x_finish - x_start) / 2) + x_start;
|
let mut x = ((x_finish - x_start) / 2) + x_start;
|
||||||
let mut y = ((y_finish - y_start) / 2) + y_start;
|
let mut y = ((y_finish - y_start) / 2) + y_start;
|
||||||
let mut x_diff = 0; //(x_finish - x_start) / 4;
|
let mut x_diff = 0;//(x_finish - x_start) / 4;
|
||||||
let mut y_diff = 0; //(y_finish - y_start) / 4;
|
let mut y_diff = 0;//(y_finish - y_start) / 4;
|
||||||
|
|
||||||
// TODO(SpaceCat~Chan): chache more stuff involved in created SegmentedArc to avoid doing so much ffi?
|
// TODO(SpaceCat~Chan): cache more stuff involved in created SegmentedArc to avoid doing so much ffi?
|
||||||
|
|
||||||
while x_diff != 0 {
|
while x_diff != 0 {
|
||||||
let segmented_arcs = arcs
|
let segmented_arcs = arcs
|
||||||
@ -884,33 +884,9 @@ fn partition_single_arc(
|
|||||||
)?;
|
)?;
|
||||||
current_coming_from = ctx.pip_location(pip).into();
|
current_coming_from = ctx.pip_location(pip).into();
|
||||||
let (before_arc, after_arc) = current_arc.split(ctx, pip);
|
let (before_arc, after_arc) = current_arc.split(ctx, pip);
|
||||||
if *from_quad == Quadrant::Northwest {
|
|
||||||
println!(
|
|
||||||
"full arc: ({:?}, {:?}, {:?}, {:?})\ninserting: ({:?}, {:?})\nsegments: {:?}\n",
|
|
||||||
arc.source_quads,
|
|
||||||
arc.estimated_source_location,
|
|
||||||
arc.sink_quads,
|
|
||||||
arc.estimated_sink_location,
|
|
||||||
before_arc.get_source_loc(),
|
|
||||||
before_arc.get_sink_loc(),
|
|
||||||
segments,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
arcs.push((*from_quad, before_arc));
|
arcs.push((*from_quad, before_arc));
|
||||||
current_arc = after_arc;
|
current_arc = after_arc;
|
||||||
}
|
}
|
||||||
if *segments.last().unwrap() == Quadrant::Northwest {
|
|
||||||
println!(
|
|
||||||
"full arc: ({:?}, {:?}, {:?}, {:?})\ninserting: ({:?}, {:?})\nsegments: {:?}\n",
|
|
||||||
arc.source_quads,
|
|
||||||
arc.estimated_source_location,
|
|
||||||
arc.sink_quads,
|
|
||||||
arc.estimated_sink_location,
|
|
||||||
current_arc.get_source_loc(),
|
|
||||||
current_arc.get_sink_loc(),
|
|
||||||
segments,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
arcs.push((*segments.last().unwrap(), current_arc));
|
arcs.push((*segments.last().unwrap(), current_arc));
|
||||||
Some(arcs)
|
Some(arcs)
|
||||||
}
|
}
|
||||||
@ -1169,8 +1145,8 @@ impl PipSelector {
|
|||||||
|
|
||||||
let src_wire = ctx.pip_src_wire(pip);
|
let src_wire = ctx.pip_src_wire(pip);
|
||||||
let dst_wire = ctx.pip_dst_wire(pip);
|
let dst_wire = ctx.pip_dst_wire(pip);
|
||||||
let src_name = ctx.name_of_wire(src_wire).to_str().unwrap();
|
let src_name = ctx.name_of_wire(src_wire);
|
||||||
let dst_name = ctx.name_of_wire(dst_wire).to_str().unwrap();
|
let dst_name = ctx.name_of_wire(dst_wire);
|
||||||
if !is_general_routing(src_name) || !is_general_routing(dst_name) {
|
if !is_general_routing(src_name) || !is_general_routing(dst_name) {
|
||||||
// ECP5 hack: whitelist allowed wires.
|
// ECP5 hack: whitelist allowed wires.
|
||||||
continue;
|
continue;
|
||||||
|
@ -232,6 +232,153 @@ impl Router {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_general_routing(&self, ctx: &npnr::Context, nets: &npnr::Nets, this: &mut RouterThread) -> Vec<Arc> {
|
||||||
|
let is_general_routing = |wire: &str| {
|
||||||
|
wire.contains("H01")
|
||||||
|
|| wire.contains("V01")
|
||||||
|
|| wire.contains("H02")
|
||||||
|
|| wire.contains("V02")
|
||||||
|
|| wire.contains("H06")
|
||||||
|
|| wire.contains("V06")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut delay = HashMap::new();
|
||||||
|
|
||||||
|
for arc in this.arcs {
|
||||||
|
delay.insert(arc, 1.0_f32);
|
||||||
|
}
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
|
||||||
|
let mut max_delay = 1.0;
|
||||||
|
let mut least_overuse = usize::MAX;
|
||||||
|
let mut iters_since_improvement = 0;
|
||||||
|
|
||||||
|
let mut route_arcs = Vec::from_iter(this.arcs.iter());
|
||||||
|
|
||||||
|
let progress = this.progress.add(ProgressBar::new(0));
|
||||||
|
progress.set_style(
|
||||||
|
ProgressStyle::with_template("[{elapsed}] [{bar:40.green/green}] {msg:30!}")
|
||||||
|
.unwrap()
|
||||||
|
.progress_chars("━╸ "),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut new_arcs = Vec::new();
|
||||||
|
let mut iterations = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
iterations += 1;
|
||||||
|
|
||||||
|
progress.set_position(0);
|
||||||
|
progress.set_length(route_arcs.len() as u64);
|
||||||
|
|
||||||
|
for arc in route_arcs.iter().sorted_by(|&i, &j| {
|
||||||
|
(delay.get(j).unwrap() / max_delay).total_cmp(&(delay.get(i).unwrap() / max_delay))
|
||||||
|
}) {
|
||||||
|
let name = ctx.name_of(arc.name).to_str().unwrap();
|
||||||
|
progress.inc(1);
|
||||||
|
let criticality = (delay.get(arc).unwrap() / max_delay).min(0.99).powf(2.5) + 0.1;
|
||||||
|
progress.set_message(format!("{} @ {}: {}", this.id, iterations, name));
|
||||||
|
*delay.get_mut(arc).unwrap() = self.route_arc(ctx, nets, arc, criticality);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut overused = HashSet::new();
|
||||||
|
for wd in self.flat_wires.iter() {
|
||||||
|
let mut wd = wd.write().unwrap();
|
||||||
|
if wd.curr_cong > 1 && !is_general_routing(ctx.name_of_wire(wd.wire)) {
|
||||||
|
overused.insert(wd.wire);
|
||||||
|
wd.hist_cong += (wd.curr_cong as f32) * self.history;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if overused.is_empty() {
|
||||||
|
break;
|
||||||
|
} else if overused.len() < least_overuse {
|
||||||
|
least_overuse = overused.len();
|
||||||
|
iters_since_improvement = 0;
|
||||||
|
progress.println(format!(
|
||||||
|
"{} @ {}: {} wires overused {}",
|
||||||
|
this.id,
|
||||||
|
iterations,
|
||||||
|
overused.len(),
|
||||||
|
"(new best)".bold()
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
iters_since_improvement += 1;
|
||||||
|
progress.println(format!(
|
||||||
|
"{} @ {}: {} wires overused",
|
||||||
|
this.id,
|
||||||
|
iterations,
|
||||||
|
overused.len()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut next_arcs = HashSet::new();
|
||||||
|
for arc in this.arcs {
|
||||||
|
let nets = &*self.nets.read().unwrap();
|
||||||
|
for wire in nets[arc.net.into_inner() as usize]
|
||||||
|
.wires
|
||||||
|
.keys()
|
||||||
|
{
|
||||||
|
if overused.contains(wire) {
|
||||||
|
next_arcs.insert(arc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for &arc in &next_arcs {
|
||||||
|
self.ripup_arc(ctx, arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let nets = &mut *self.nets.write().unwrap();
|
||||||
|
for net in nets.iter_mut() {
|
||||||
|
net.done_sinks.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if iters_since_improvement > 50 {
|
||||||
|
iters_since_improvement = 0;
|
||||||
|
least_overuse = usize::MAX;
|
||||||
|
progress.println(format!(
|
||||||
|
"{} @ {}: {}",
|
||||||
|
this.id,
|
||||||
|
iterations,
|
||||||
|
"bored; rerouting everything".bold()
|
||||||
|
));
|
||||||
|
route_arcs = Vec::from_iter(this.arcs.iter());
|
||||||
|
} else {
|
||||||
|
route_arcs = Vec::from_iter(next_arcs.into_iter());
|
||||||
|
}
|
||||||
|
|
||||||
|
max_delay = this
|
||||||
|
.arcs
|
||||||
|
.iter()
|
||||||
|
.map(|arc| *delay.get(arc).unwrap())
|
||||||
|
.reduce(f32::max)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let now = start.elapsed().as_secs_f32();
|
||||||
|
progress.println(format!(
|
||||||
|
"{} @ {}: {} in {:.0}m{:.03}s",
|
||||||
|
this.id,
|
||||||
|
iterations,
|
||||||
|
"pre-routing complete".green(),
|
||||||
|
(now / 60.0).floor(),
|
||||||
|
now % 60.0
|
||||||
|
));
|
||||||
|
|
||||||
|
progress.finish_and_clear();
|
||||||
|
|
||||||
|
for arc in this.arcs {
|
||||||
|
let (source_wire, sink_wire) = self.ripup_arc_general_routing(ctx, arc);
|
||||||
|
new_arcs.push(Arc::new(source_wire, None, sink_wire, None, arc.net, arc.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
new_arcs
|
||||||
|
}
|
||||||
|
|
||||||
pub fn route(&self, ctx: &npnr::Context, nets: &npnr::Nets, this: &mut RouterThread) {
|
pub fn route(&self, ctx: &npnr::Context, nets: &npnr::Nets, this: &mut RouterThread) {
|
||||||
let mut delay = HashMap::new();
|
let mut delay = HashMap::new();
|
||||||
|
|
||||||
@ -267,7 +414,7 @@ impl Router {
|
|||||||
}) {
|
}) {
|
||||||
let name = ctx.name_of(arc.name).to_str().unwrap();
|
let name = ctx.name_of(arc.name).to_str().unwrap();
|
||||||
progress.inc(1);
|
progress.inc(1);
|
||||||
let criticality = (delay.get(arc).unwrap() / max_delay).min(0.99).powf(2.5) + 0.1;
|
let criticality = (delay.get(arc).unwrap() / max_delay);
|
||||||
progress.set_message(format!("{} @ {}: {}", this.id, iterations, name));
|
progress.set_message(format!("{} @ {}: {}", this.id, iterations, name));
|
||||||
*delay.get_mut(arc).unwrap() = self.route_arc(ctx, nets, arc, criticality);
|
*delay.get_mut(arc).unwrap() = self.route_arc(ctx, nets, arc, criticality);
|
||||||
}
|
}
|
||||||
@ -303,24 +450,28 @@ impl Router {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut next_arcs = Vec::new();
|
let mut next_arcs = HashSet::new();
|
||||||
for arc in this.arcs {
|
for arc in this.arcs {
|
||||||
for wire in self.nets.read().unwrap()[arc.net.into_inner() as usize]
|
let nets = &*self.nets.read().unwrap();
|
||||||
|
for wire in nets[arc.net.into_inner() as usize]
|
||||||
.wires
|
.wires
|
||||||
.keys()
|
.keys()
|
||||||
{
|
{
|
||||||
if overused.contains(wire) {
|
if overused.contains(wire) {
|
||||||
next_arcs.push(arc);
|
next_arcs.insert(arc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for &arc in &route_arcs {
|
for &arc in &next_arcs {
|
||||||
self.ripup_arc(ctx, arc);
|
self.ripup_arc(ctx, arc);
|
||||||
}
|
}
|
||||||
for net in self.nets.write().unwrap().iter_mut() {
|
{
|
||||||
|
let nets = &mut *self.nets.write().unwrap();
|
||||||
|
for net in nets.iter_mut() {
|
||||||
net.done_sinks.clear();
|
net.done_sinks.clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if iters_since_improvement > 50 {
|
if iters_since_improvement > 50 {
|
||||||
iters_since_improvement = 0;
|
iters_since_improvement = 0;
|
||||||
@ -333,7 +484,7 @@ impl Router {
|
|||||||
));
|
));
|
||||||
route_arcs = Vec::from_iter(this.arcs.iter());
|
route_arcs = Vec::from_iter(this.arcs.iter());
|
||||||
} else {
|
} else {
|
||||||
route_arcs = next_arcs;
|
route_arcs = Vec::from_iter(next_arcs.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
max_delay = this
|
max_delay = this
|
||||||
@ -492,20 +643,6 @@ impl Router {
|
|||||||
dirty_wires.push(source_wire);
|
dirty_wires.push(source_wire);
|
||||||
dirty_wires.push(sink_wire);
|
dirty_wires.push(sink_wire);
|
||||||
|
|
||||||
let already_done = self.nets.read().unwrap()[arc.net().into_inner() as usize]
|
|
||||||
.done_sinks
|
|
||||||
.contains(&arc.sink_wire);
|
|
||||||
if already_done {
|
|
||||||
midpoint = Some(*self.wire_to_idx.get(&arc.sink_wire).unwrap());
|
|
||||||
|
|
||||||
let mut wire = arc.sink_wire();
|
|
||||||
while wire != arc.source_wire() {
|
|
||||||
let nd = &self.nets.read().unwrap()[arc.net().into_inner() as usize];
|
|
||||||
let driver = nd.wires.get(&wire).unwrap().0;
|
|
||||||
self.set_visited_fwd(self.wire_to_idx[&wire], driver, &mut dirty_wires);
|
|
||||||
wire = ctx.pip_src_wire(driver);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while midpoint.is_none() {
|
while midpoint.is_none() {
|
||||||
// Step forward
|
// Step forward
|
||||||
if !self.step(
|
if !self.step(
|
||||||
@ -526,7 +663,7 @@ impl Router {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Step backward
|
// Step backward
|
||||||
/*if !self.step(
|
if !self.step(
|
||||||
ctx,
|
ctx,
|
||||||
nets,
|
nets,
|
||||||
arc,
|
arc,
|
||||||
@ -542,7 +679,7 @@ impl Router {
|
|||||||
npnr::Context::pip_src_wire,
|
npnr::Context::pip_src_wire,
|
||||||
) {
|
) {
|
||||||
break;
|
break;
|
||||||
}*/
|
}
|
||||||
self.flat_wires[source_wire as usize]
|
self.flat_wires[source_wire as usize]
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -552,14 +689,13 @@ impl Router {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.visited_bwd = true;
|
.visited_bwd = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
midpoint.is_some(),
|
midpoint.is_some(),
|
||||||
"didn't find sink wire for net {} between {} and {}",
|
"didn't find sink wire for net {} between {} and {}",
|
||||||
ctx.name_of(arc.name).to_str().unwrap(),
|
ctx.name_of(arc.name).to_str().unwrap(),
|
||||||
ctx.name_of_wire(arc.source_wire).to_str().unwrap(),
|
ctx.name_of_wire(arc.source_wire),
|
||||||
ctx.name_of_wire(arc.sink_wire).to_str().unwrap(),
|
ctx.name_of_wire(arc.sink_wire),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut wire = midpoint.unwrap();
|
let mut wire = midpoint.unwrap();
|
||||||
@ -665,6 +801,43 @@ impl Router {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ripup_arc_general_routing(&self, ctx: &npnr::Context, arc: &Arc) -> (WireId, WireId) {
|
||||||
|
let is_general_routing = |wire: WireId| {
|
||||||
|
let wire = ctx.name_of_wire(wire);
|
||||||
|
wire.contains("H01")
|
||||||
|
|| wire.contains("V01")
|
||||||
|
|| wire.contains("H02")
|
||||||
|
|| wire.contains("V02")
|
||||||
|
|| wire.contains("H06")
|
||||||
|
|| wire.contains("V06")
|
||||||
|
};
|
||||||
|
|
||||||
|
let net = arc.net().into_inner() as usize;
|
||||||
|
let source_wire = arc.source_wire;
|
||||||
|
let mut wire = arc.sink_wire;
|
||||||
|
let mut last_was_general = false;
|
||||||
|
let mut w1 = arc.sink_wire;
|
||||||
|
let mut w2 = arc.source_wire;
|
||||||
|
while wire != source_wire {
|
||||||
|
let pip = self.nets.read().unwrap()[net].wires.get(&wire).expect("wire should have driving pip").0;
|
||||||
|
assert!(pip != PipId::null());
|
||||||
|
if is_general_routing(wire) {
|
||||||
|
if !last_was_general {
|
||||||
|
w1 = wire;
|
||||||
|
}
|
||||||
|
self.unbind_pip_internal(arc.net(), wire);
|
||||||
|
last_was_general = true;
|
||||||
|
} else {
|
||||||
|
if last_was_general {
|
||||||
|
w2 = wire;
|
||||||
|
}
|
||||||
|
last_was_general = false;
|
||||||
|
}
|
||||||
|
wire = ctx.pip_src_wire(pip);
|
||||||
|
}
|
||||||
|
(w2, w1)
|
||||||
|
}
|
||||||
|
|
||||||
fn reset_wires(&self, dirty_wires: &Vec<u32>) {
|
fn reset_wires(&self, dirty_wires: &Vec<u32>) {
|
||||||
for &wire in dirty_wires {
|
for &wire in dirty_wires {
|
||||||
let mut nwd = self.flat_wires[wire as usize].write().unwrap();
|
let mut nwd = self.flat_wires[wire as usize].write().unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user