awooter: (bad) router congestion heuristics
This commit is contained in:
parent
1375277171
commit
cbee9f1e5f
@ -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());
|
||||
|
@ -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 {
|
||||
|
@ -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));
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user