diff --git a/common/route/awooter/rust/src/lib.rs b/common/route/awooter/rust/src/lib.rs index d1ab7823..2ab294e5 100644 --- a/common/route/awooter/rust/src/lib.rs +++ b/common/route/awooter/rust/src/lib.rs @@ -214,27 +214,30 @@ fn route(ctx: &mut npnr::Context) -> bool { let progress = MultiProgress::new(); let partitions = [ - (Coord::new(0, 0), Coord::new(x_part + 1, y_part + 1), &ne), + (Coord::new(0, 0), Coord::new(x_part + 1, y_part + 1), &ne, "NE"), ( Coord::new(x_part - 1, 0), Coord::new(ctx.grid_dim_x(), y_part + 1), &se, + "SE" ), ( Coord::new(x_part - 1, y_part - 1), Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()), &sw, + "SW" ), ( Coord::new(0, y_part - 1), Coord::new(x_part + 1, ctx.grid_dim_y()), &nw, + "NW" ), ]; - partitions.par_iter().for_each(|(box_ne, box_sw, arcs)| { + partitions.par_iter().for_each(|(box_ne, box_sw, arcs, id)| { let mut router = route::Router::new(*box_ne, *box_sw); - router.route(ctx, &nets, wires, arcs, &progress); + router.route(ctx, &nets, wires, arcs, &progress, id); }); log_info!("Routing miscellaneous arcs\n"); @@ -242,7 +245,7 @@ fn route(ctx: &mut npnr::Context) -> bool { Coord::new(0, 0), Coord::new(ctx.grid_dim_x(), ctx.grid_dim_y()), ); - router.route(ctx, &nets, wires, &special_arcs, &progress); + router.route(ctx, &nets, wires, &special_arcs, &progress, "MISC"); let time = format!("{:.2}", (Instant::now() - start).as_secs_f32()); log_info!("Routing took {}s\n", time.bold()); diff --git a/common/route/awooter/rust/src/npnr.rs b/common/route/awooter/rust/src/npnr.rs index cd152034..b245489e 100644 --- a/common/route/awooter/rust/src/npnr.rs +++ b/common/route/awooter/rust/src/npnr.rs @@ -356,7 +356,11 @@ extern "C-unwind" { fn npnr_context_get_pips_leak(ctx: *const Context, pips: *mut *mut PipId) -> u64; fn npnr_context_get_pip_location(ctx: *const Context, pip: PipId) -> Loc; fn npnr_context_get_pip_direction(ctx: *const Context, pip: PipId) -> Loc; - fn npnr_context_check_pip_avail_for_net(ctx: *const Context, pip: PipId, net: *const NetInfo) -> bool; + fn npnr_context_check_pip_avail_for_net( + ctx: *const Context, + pip: PipId, + net: *const NetInfo, + ) -> bool; fn npnr_context_check(ctx: *const Context); fn npnr_context_debug(ctx: *const Context) -> bool; @@ -446,7 +450,9 @@ impl<'a> Nets<'a> { let index = index_to_net.len() as i32; index_to_net.push(name); net_to_index.insert(net, index); - unsafe { npnr_netinfo_udata_set(net, NetIndex(index)); } + unsafe { + npnr_netinfo_udata_set(net, NetIndex(index)); + } } // Note: the contents of `names` and `nets_ptr` are now lost. Self { diff --git a/common/route/awooter/rust/src/partition.rs b/common/route/awooter/rust/src/partition.rs index db3a0357..80ff8810 100644 --- a/common/route/awooter/rust/src/partition.rs +++ b/common/route/awooter/rust/src/partition.rs @@ -307,7 +307,11 @@ fn partition>( let sink_coords: Coord = sink_loc.into(); let sink_is_north = sink_coords.is_north_of(&partition_coords); let sink_is_east = sink_coords.is_east_of(&partition_coords); - let name = ctx.name_of(nets.name_from_index(arc.net())).to_str().unwrap().to_string(); + let name = ctx + .name_of(nets.name_from_index(arc.net())) + .to_str() + .unwrap() + .to_string(); let verbose = false; //name == "soc0.processor.with_fpu.fpu_0.fpu_multiply_0.rin_CCU2C_S0_4$CCU2_FCI_INT"; if source_is_north == sink_is_north && source_is_east == sink_is_east { let seg = source_coords.segment_from(&Coord::new(x, y)); @@ -626,7 +630,7 @@ pub fn find_partition_point_and_sanity_check( y_finish: i32, ) -> (i32, i32, Vec, Vec, Vec, Vec) { let (x_part, y_part, ne, se, sw, nw) = - find_partition_point(ctx, nets, arcs, pips, x_start, x_finish, y_start, y_finish); + find_partition_point(ctx, nets, arcs, pips, x_start, x_finish, y_start, y_finish); let mut invalid_arcs_in_ne = 0; let mut invalid_arcs_in_se = 0; diff --git a/common/route/awooter/rust/src/route.rs b/common/route/awooter/rust/src/route.rs index 449c5e04..4e2feff1 100644 --- a/common/route/awooter/rust/src/route.rs +++ b/common/route/awooter/rust/src/route.rs @@ -73,20 +73,21 @@ impl Arc { #[derive(Copy, Clone)] struct QueuedWire { - cost: f32, + delay: f32, + congest: f32, togo: f32, wire: npnr::WireId, } impl QueuedWire { - pub fn new(cost: f32, togo: f32, wire: npnr::WireId) -> Self { - Self { cost, togo, wire } + pub fn new(delay: f32, congest: f32, togo: f32, wire: npnr::WireId) -> Self { + Self { delay, congest, togo, wire } } } impl PartialEq for QueuedWire { fn eq(&self, other: &Self) -> bool { - self.cost == other.cost && self.togo == other.togo && self.wire == other.wire + self.delay == other.delay && self.congest == other.congest && self.togo == other.togo && self.wire == other.wire } } @@ -94,8 +95,8 @@ 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; + let me = (0.9 * self.delay) + (0.1 * self.congest) + self.togo; + let other = (0.9 * other.delay) + (0.1 * other.congest) + other.togo; other.total_cmp(&me) } } @@ -106,13 +107,12 @@ impl PartialOrd for QueuedWire { } } - struct PerNetData { wires: HashMap, } struct PerWireData { - wire: WireId, + wire: WireId, curr_cong: u32, hist_cong: f32, unavailable: bool, @@ -130,6 +130,9 @@ pub struct Router { dirty_wires: Vec, } +const PRESSURE_FACTOR: u32 = 5; +const ACCUMULATED_OVERUSE_FACTOR: f32 = 5.0; + impl Router { pub fn new(box_ne: partition::Coord, box_sw: partition::Coord) -> Self { Self { @@ -149,10 +152,12 @@ impl Router { wires: &[npnr::WireId], arcs: &[Arc], progress: &MultiProgress, + id: &str, ) { - log_info!("Setting up router...\n"); for _ in 0..nets.len() { - self.nets.push(PerNetData { wires: HashMap::new() }); + self.nets.push(PerNetData { + wires: HashMap::new(), + }); } for (idx, &wire) in wires.iter().enumerate() { @@ -163,40 +168,56 @@ impl Router { unavailable: false, reserved_net: None, pip_fwd: PipId::null(), - visited_fwd: false + visited_fwd: false, }); self.wire_to_idx.insert(wire, idx as u32); } - let progress = progress.add(ProgressBar::new(arcs.len() as u64)); - progress.set_style( - ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}") - .unwrap() - .progress_chars("━╸ "), - ); + loop { + let progress = progress.add(ProgressBar::new(arcs.len() as u64)); + progress.set_style( + ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}") + .unwrap() + .progress_chars("━╸ "), + ); - for arc in arcs { - let net = unsafe { nets.net_from_index(arc.net).as_ref().unwrap() }; - let name = ctx - .name_of(nets.name_from_index(arc.net)) - .to_str() - .unwrap() - .to_string(); + for arc in arcs { + let net = unsafe { nets.net_from_index(arc.net).as_ref().unwrap() }; + let name = ctx + .name_of(nets.name_from_index(arc.net)) + .to_str() + .unwrap(); - if net.is_global() { - continue; + if net.is_global() { + continue; + } + + progress.inc(1); + progress.set_message(format!("{} @ {}", id, name)); + self.route_arc(ctx, nets, arc); } - - progress.inc(1); - progress.set_message(name); - self.route_arc(ctx, nets, arc); + progress.finish_and_clear(); + + let mut overused = 0; + for wd in &mut self.flat_wires { + if wd.curr_cong > 1 { + overused += 1; + wd.hist_cong += (wd.curr_cong as f32) * ACCUMULATED_OVERUSE_FACTOR; + } + wd.curr_cong = 0; + } + + if overused == 0 { + break; + } + + progress.println(format!("{}: {} wires overused", id, overused)); } - progress.finish_and_clear() } fn route_arc(&mut self, ctx: &npnr::Context, nets: &npnr::Nets, arc: &Arc) { let mut queue = BinaryHeap::new(); - queue.push(QueuedWire::new(0.0, 0.0, arc.source_wire)); + queue.push(QueuedWire::new(0.0, 0.0, 0.0, arc.source_wire)); let mut found_sink = false; @@ -272,11 +293,13 @@ impl Router { continue; } + let node_delay = ctx.pip_delay(pip) + ctx.wire_delay(wire) + ctx.delay_epsilon(); + let delay = source.delay + node_delay; + let congest = source.congest + (node_delay + nwd.hist_cong) * (1.0 + (nwd.curr_cong * PRESSURE_FACTOR) as f32); + self.set_visited_fwd(sink, pip); - let delay = - source.cost + ctx.pip_delay(pip) + ctx.wire_delay(wire) + ctx.delay_epsilon(); - let qw = QueuedWire::new(delay, ctx.estimate_delay(wire, arc.sink_wire), wire); + let qw = QueuedWire::new(delay, congest, ctx.estimate_delay(wire, arc.sink_wire), wire); queue.push(qw); } } @@ -293,7 +316,12 @@ impl Router { let mut wire = *self.wire_to_idx.get(&arc.sink_wire).unwrap(); while wire != source_wire { if verbose { - println!("Wire: {}", ctx.name_of_wire(self.flat_wires[wire as usize].wire).to_str().unwrap()); + println!( + "Wire: {}", + ctx.name_of_wire(self.flat_wires[wire as usize].wire) + .to_str() + .unwrap() + ); } let pip = self.flat_wires[wire as usize].pip_fwd; assert!(pip != PipId::null()); @@ -328,7 +356,7 @@ impl Router { self.flat_wires[wire as usize].curr_cong += 1; } } - + fn reset_wires(&mut self) { for &wire in &self.dirty_wires { self.flat_wires[wire as usize].pip_fwd = PipId::null();