awooter: (bad) router congestion heuristics

This commit is contained in:
Lofty 2022-12-03 21:07:07 +00:00
parent 1375277171
commit cbee9f1e5f
4 changed files with 86 additions and 45 deletions

View File

@ -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());

View File

@ -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 {

View File

@ -307,7 +307,11 @@ fn partition<R: RangeBounds<i32>>(
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));

View File

@ -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,7 +107,6 @@ impl PartialOrd for QueuedWire {
}
}
struct PerNetData {
wires: HashMap<WireId, (PipId, u32)>,
}
@ -130,6 +130,9 @@ pub struct Router {
dirty_wires: Vec<u32>,
}
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,11 +168,12 @@ 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);
}
loop {
let progress = progress.add(ProgressBar::new(arcs.len() as u64));
progress.set_style(
ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}")
@ -180,23 +186,38 @@ impl Router {
let name = ctx
.name_of(nets.name_from_index(arc.net))
.to_str()
.unwrap()
.to_string();
.unwrap();
if net.is_global() {
continue;
}
progress.inc(1);
progress.set_message(name);
progress.set_message(format!("{} @ {}", id, name));
self.route_arc(ctx, nets, arc);
}
progress.finish_and_clear()
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));
}
}
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());