awooter: partitioner improvements
This commit is contained in:
parent
8fd983af15
commit
522dd3da7c
@ -214,15 +214,12 @@ extern "C" {
|
|||||||
bool npnr_context_debug(const Context *const ctx) { return ctx->debug; }
|
bool npnr_context_debug(const Context *const ctx) { return ctx->debug; }
|
||||||
int npnr_context_id(const Context *const ctx, const char *const str) { return ctx->id(str).hash(); }
|
int npnr_context_id(const Context *const ctx, const char *const str) { return ctx->id(str).hash(); }
|
||||||
const char *npnr_context_name_of(const Context *const ctx, IdString str) { return ctx->nameOf(str); }
|
const char *npnr_context_name_of(const Context *const ctx, IdString str) { return ctx->nameOf(str); }
|
||||||
|
const char *npnr_context_name_of_pip(const Context *const ctx, uint64_t pip) { return ctx->nameOfPip(unwrap_pip(pip)); }
|
||||||
|
const char *npnr_context_name_of_wire(const Context *const ctx, uint64_t wire) { return ctx->nameOfWire(unwrap_wire(wire)); }
|
||||||
bool npnr_context_verbose(const Context *const ctx) { return ctx->verbose; }
|
bool npnr_context_verbose(const Context *const ctx) { return ctx->verbose; }
|
||||||
|
|
||||||
uint64_t npnr_context_get_netinfo_source_wire(const Context *const ctx, const NetInfo *const net) { return wrap(ctx->getNetinfoSourceWire(net)); }
|
uint64_t npnr_context_get_netinfo_source_wire(const Context *const ctx, const NetInfo *const net) { return wrap(ctx->getNetinfoSourceWire(net)); }
|
||||||
uint64_t npnr_context_get_netinfo_sink_wire(const Context *const ctx, const NetInfo *const net, const PortRef *const sink, uint32_t n) {
|
uint64_t npnr_context_get_netinfo_sink_wire(const Context *const ctx, const NetInfo *const net, const PortRef *const sink, uint32_t n) { return wrap(ctx->getNetinfoSinkWire(net, *sink, n)); }
|
||||||
if (ctx == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return wrap(ctx->getNetinfoSinkWire(net, *sink, n));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t npnr_context_nets_leak(const Context *const ctx, int **names, NetInfo ***nets) {
|
uint32_t npnr_context_nets_leak(const Context *const ctx, int **names, NetInfo ***nets) {
|
||||||
auto name_vec = std::vector<int>{};
|
auto name_vec = std::vector<int>{};
|
||||||
|
@ -23,9 +23,9 @@ pub extern "C" fn npnr_router_awooter(ctx: Option<NonNull<npnr::Context>>) -> bo
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_arcs_from_nets(ctx: &npnr::Context, nets: npnr::Nets) -> Vec<route::Arc> {
|
fn extract_arcs_from_nets(ctx: &npnr::Context, nets: &npnr::Nets) -> Vec<route::Arc> {
|
||||||
let mut arcs = vec![];
|
let mut arcs = vec![];
|
||||||
for (name, net) in nets.iter() {
|
for (name, net) in nets.to_vec().iter() {
|
||||||
let net = unsafe { net.as_mut().unwrap() };
|
let net = unsafe { net.as_mut().unwrap() };
|
||||||
if net.is_global() {
|
if net.is_global() {
|
||||||
continue;
|
continue;
|
||||||
@ -36,7 +36,7 @@ fn extract_arcs_from_nets(ctx: &npnr::Context, nets: npnr::Nets) -> Vec<route::A
|
|||||||
let source = cell.location();
|
let source = cell.location();
|
||||||
let source_wire = ctx.source_wire(net);
|
let source_wire = ctx.source_wire(net);
|
||||||
|
|
||||||
for sink_ref in nets.users_by_name(*name).unwrap().iter() {
|
for sink_ref in nets.users_by_name(**name).unwrap().iter() {
|
||||||
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) {
|
||||||
@ -81,10 +81,10 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
log_info!("Found {} nets\n", nets_str.bold());
|
log_info!("Found {} nets\n", nets_str.bold());
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
for (name, net) in nets.iter() {
|
for (&name, net) in nets.to_vec().iter() {
|
||||||
let _src = ctx.source_wire(*net);
|
let _src = ctx.source_wire(**net);
|
||||||
let net = unsafe { net.as_mut().unwrap() };
|
let net = unsafe { net.as_mut().unwrap() };
|
||||||
let users = nets.users_by_name(*name).unwrap().iter();
|
let users = nets.users_by_name(name).unwrap().iter();
|
||||||
for user in users {
|
for user in users {
|
||||||
count += ctx.sink_wires(net, *user).len();
|
count += ctx.sink_wires(net, *user).len();
|
||||||
}
|
}
|
||||||
@ -92,7 +92,9 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
|
|
||||||
log_info!("Found {} arcs\n", count.to_string().bold());
|
log_info!("Found {} arcs\n", count.to_string().bold());
|
||||||
|
|
||||||
let (name, net) = nets
|
let binding = nets
|
||||||
|
.to_vec();
|
||||||
|
let (name, net) = binding
|
||||||
.iter()
|
.iter()
|
||||||
.max_by_key(|(name, net)| {
|
.max_by_key(|(name, net)| {
|
||||||
let net = unsafe { net.as_mut().unwrap() };
|
let net = unsafe { net.as_mut().unwrap() };
|
||||||
@ -109,7 +111,7 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
|
|
||||||
let net = unsafe { net.as_mut().unwrap() };
|
let net = unsafe { net.as_mut().unwrap() };
|
||||||
let count = nets
|
let count = nets
|
||||||
.users_by_name(*name)
|
.users_by_name(**name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.fold(0, |acc, sink| acc + ctx.sink_wires(net, *sink).len())
|
.fold(0, |acc, sink| acc + ctx.sink_wires(net, *sink).len())
|
||||||
@ -117,7 +119,7 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
|
|
||||||
log_info!(
|
log_info!(
|
||||||
"Highest non-global fanout net is {}\n",
|
"Highest non-global fanout net is {}\n",
|
||||||
ctx.name_of(*name).to_str().unwrap().bold()
|
ctx.name_of(**name).to_str().unwrap().bold()
|
||||||
);
|
);
|
||||||
log_info!(" with {} arcs\n", count.bold());
|
log_info!(" with {} arcs\n", count.bold());
|
||||||
|
|
||||||
@ -126,7 +128,7 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
let mut x1 = 0;
|
let mut x1 = 0;
|
||||||
let mut y1 = 0;
|
let mut y1 = 0;
|
||||||
|
|
||||||
for sink in nets.users_by_name(*name).unwrap().iter() {
|
for sink in nets.users_by_name(**name).unwrap().iter() {
|
||||||
let cell = sink.cell().unwrap().location();
|
let cell = sink.cell().unwrap().location();
|
||||||
x0 = x0.min(cell.x);
|
x0 = x0.min(cell.x);
|
||||||
y0 = y0.min(cell.y);
|
y0 = y0.min(cell.y);
|
||||||
@ -147,12 +149,15 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
rayon::current_num_threads().to_string().bold()
|
rayon::current_num_threads().to_string().bold()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
let arcs = extract_arcs_from_nets(ctx, nets);
|
let arcs = extract_arcs_from_nets(ctx, &nets);
|
||||||
|
|
||||||
let (x_part, y_part, ne, se, sw, nw) = partition::find_partition_point_and_sanity_check(
|
let (x_part, y_part, ne, se, sw, nw) = partition::find_partition_point_and_sanity_check(
|
||||||
ctx,
|
ctx,
|
||||||
|
&nets,
|
||||||
&arcs[..],
|
&arcs[..],
|
||||||
pips,
|
pips,
|
||||||
0,
|
0,
|
||||||
@ -166,7 +171,7 @@ fn route(ctx: &mut npnr::Context) -> bool {
|
|||||||
log_info!("Partitioning took {:.2}s\n", time.as_secs_f32());
|
log_info!("Partitioning took {:.2}s\n", time.as_secs_f32());
|
||||||
|
|
||||||
let mut router = route::Router::new(Coord::new(0, 0), Coord::new(x_part, y_part));
|
let mut router = route::Router::new(Coord::new(0, 0), Coord::new(x_part, y_part));
|
||||||
router.route(ctx, &ne);
|
router.route(ctx, &nets, &ne);
|
||||||
|
|
||||||
/*log_info!("=== level 2 NE:\n");
|
/*log_info!("=== level 2 NE:\n");
|
||||||
let _ = find_partition_point(&ne, x_start, x, y_start, y);
|
let _ = find_partition_point(&ne, x_start, x, y_start, y);
|
||||||
|
@ -278,6 +278,14 @@ impl Context {
|
|||||||
unsafe { CStr::from_ptr(npnr_context_name_of(self, s)) }
|
unsafe { CStr::from_ptr(npnr_context_name_of(self, s)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name_of_pip(&self, pip: PipId) -> &CStr {
|
||||||
|
unsafe { CStr::from_ptr(npnr_context_name_of_pip(self, pip)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name_of_wire(&self, wire: WireId) -> &CStr {
|
||||||
|
unsafe { CStr::from_ptr(npnr_context_name_of_wire(self, wire)) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn verbose(&self) -> bool {
|
pub fn verbose(&self) -> bool {
|
||||||
unsafe { npnr_context_verbose(self) }
|
unsafe { npnr_context_verbose(self) }
|
||||||
}
|
}
|
||||||
@ -331,6 +339,8 @@ extern "C" {
|
|||||||
fn npnr_context_debug(ctx: *const Context) -> bool;
|
fn npnr_context_debug(ctx: *const Context) -> bool;
|
||||||
fn npnr_context_id(ctx: *const Context, s: *const c_char) -> IdString;
|
fn npnr_context_id(ctx: *const Context, s: *const c_char) -> IdString;
|
||||||
fn npnr_context_name_of(ctx: *const Context, s: IdString) -> *const libc::c_char;
|
fn npnr_context_name_of(ctx: *const Context, s: IdString) -> *const libc::c_char;
|
||||||
|
fn npnr_context_name_of_pip(ctx: *const Context, pip: PipId) -> *const libc::c_char;
|
||||||
|
fn npnr_context_name_of_wire(ctx: *const Context, wire: WireId) -> *const libc::c_char;
|
||||||
fn npnr_context_verbose(ctx: *const Context) -> bool;
|
fn npnr_context_verbose(ctx: *const Context) -> bool;
|
||||||
|
|
||||||
fn npnr_context_get_netinfo_source_wire(ctx: *const Context, net: *const NetInfo) -> WireId;
|
fn npnr_context_get_netinfo_source_wire(ctx: *const Context, net: *const NetInfo) -> WireId;
|
||||||
@ -376,6 +386,9 @@ pub struct Nets<'a> {
|
|||||||
_data: PhantomData<&'a Context>,
|
_data: PhantomData<&'a Context>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for Nets<'_> {}
|
||||||
|
unsafe impl Sync for Nets<'_> {}
|
||||||
|
|
||||||
impl<'a> Nets<'a> {
|
impl<'a> Nets<'a> {
|
||||||
/// Create a new store for the nets of a context.
|
/// Create a new store for the nets of a context.
|
||||||
///
|
///
|
||||||
@ -430,8 +443,19 @@ impl<'a> Nets<'a> {
|
|||||||
self.nets.len()
|
self.nets.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> std::collections::hash_map::Iter<'_, IdString, *mut NetInfo> {
|
pub fn name_from_index(&self, index: NetIndex) -> IdString {
|
||||||
self.nets.iter()
|
self.index_to_net[index.0 as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn net_from_index(&self, index: NetIndex) -> *mut NetInfo {
|
||||||
|
*self.nets.get(&self.name_from_index(index)).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_vec(&self) -> Vec<(&IdString, &*mut NetInfo)> {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
v.extend(self.nets.iter());
|
||||||
|
v.sort_by_key(|(name, _net)| name.0);
|
||||||
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ impl From<npnr::Loc> for Coord {
|
|||||||
|
|
||||||
pub fn find_partition_point(
|
pub fn find_partition_point(
|
||||||
ctx: &npnr::Context,
|
ctx: &npnr::Context,
|
||||||
|
nets: &npnr::Nets,
|
||||||
arcs: &[Arc],
|
arcs: &[Arc],
|
||||||
pips: &[npnr::PipId],
|
pips: &[npnr::PipId],
|
||||||
x_start: i32,
|
x_start: i32,
|
||||||
@ -91,6 +92,7 @@ pub fn find_partition_point(
|
|||||||
while x_diff != 0 {
|
while x_diff != 0 {
|
||||||
(ne, se, sw, nw) = partition(
|
(ne, se, sw, nw) = partition(
|
||||||
ctx,
|
ctx,
|
||||||
|
nets,
|
||||||
arcs,
|
arcs,
|
||||||
pips,
|
pips,
|
||||||
x,
|
x,
|
||||||
@ -135,6 +137,7 @@ pub fn find_partition_point(
|
|||||||
|
|
||||||
(ne, se, sw, nw) = partition(
|
(ne, se, sw, nw) = partition(
|
||||||
ctx,
|
ctx,
|
||||||
|
nets,
|
||||||
arcs,
|
arcs,
|
||||||
pips,
|
pips,
|
||||||
x,
|
x,
|
||||||
@ -200,6 +203,7 @@ fn split_line_over_y(line: (npnr::Loc, npnr::Loc), y_location: i32) -> i32 {
|
|||||||
// A big thank you to @Spacecat-chan for fixing my broken and buggy partition code.
|
// A big thank you to @Spacecat-chan for fixing my broken and buggy partition code.
|
||||||
fn partition<R: RangeBounds<i32>>(
|
fn partition<R: RangeBounds<i32>>(
|
||||||
ctx: &npnr::Context,
|
ctx: &npnr::Context,
|
||||||
|
nets: &npnr::Nets,
|
||||||
arcs: &[Arc],
|
arcs: &[Arc],
|
||||||
pips: &[npnr::PipId],
|
pips: &[npnr::PipId],
|
||||||
x: i32,
|
x: i32,
|
||||||
@ -243,6 +247,22 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
if loc.x == x && loc.y == y {
|
if loc.x == x && loc.y == y {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 src_wire = ctx.pip_src_wire(pip);
|
||||||
|
let dst_wire = ctx.pip_dst_wire(pip);
|
||||||
|
let src_name = ctx.name_of_wire(src_wire).to_str().unwrap();
|
||||||
|
let dst_name = ctx.name_of_wire(dst_wire).to_str().unwrap();
|
||||||
|
if !is_general_routing(src_name) || !is_general_routing(dst_name) {
|
||||||
|
// ECP5 hack: whitelist allowed wires.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
candidates += 1;
|
candidates += 1;
|
||||||
|
|
||||||
let pip_arc = std::sync::Arc::new((pip, AtomicUsize::new(0)));
|
let pip_arc = std::sync::Arc::new((pip, AtomicUsize::new(0)));
|
||||||
@ -328,7 +348,7 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
|
|
||||||
let progress = ProgressBar::new(arcs.len() as u64);
|
let progress = ProgressBar::new(arcs.len() as u64);
|
||||||
progress.set_style(
|
progress.set_style(
|
||||||
ProgressStyle::with_template("[{elapsed}] [{bar:40.cyan/blue}] {msg}")
|
ProgressStyle::with_template("[{elapsed}] [{bar:40.cyan/blue}] {msg:30!}")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.progress_chars("━╸ "),
|
.progress_chars("━╸ "),
|
||||||
);
|
);
|
||||||
@ -362,6 +382,8 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
let sink_coords: Coord = sink_loc.into();
|
let sink_coords: Coord = sink_loc.into();
|
||||||
let sink_is_north = sink_coords.is_north_of(&partition_coords);
|
let sink_is_north = sink_coords.is_north_of(&partition_coords);
|
||||||
let sink_is_east = sink_coords.is_east_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 verbose = name == "decode_to_execute_IS_RS2_SIGNED_LUT4_D_1_Z_CCU2C_B1_S0_CCU2C_S0_3_B1";
|
||||||
if source_is_north == sink_is_north && source_is_east == sink_is_east {
|
if source_is_north == sink_is_north && source_is_east == sink_is_east {
|
||||||
let seg = source_coords.segment_from(&Coord::new(x, y));
|
let seg = source_coords.segment_from(&Coord::new(x, y));
|
||||||
vec![(seg, arc.clone())]
|
vec![(seg, arc.clone())]
|
||||||
@ -383,6 +405,10 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
let selected_pip = find_best_pip(pips, arc);
|
let selected_pip = find_best_pip(pips, arc);
|
||||||
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
log_info!("split arc {} to {} vertically across pip {}\n", ctx.name_of_wire(arc.get_source_wire()).to_str().unwrap(), ctx.name_of_wire(arc.get_sink_wire()).to_str().unwrap(), ctx.name_of_pip(selected_pip).to_str().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip);
|
let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip);
|
||||||
let (seg1, seg2) = match (source_is_north, source_is_east) {
|
let (seg1, seg2) = match (source_is_north, source_is_east) {
|
||||||
(true, true) => (Segment::Northeast, Segment::Southeast),
|
(true, true) => (Segment::Northeast, Segment::Southeast),
|
||||||
@ -410,6 +436,10 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
let selected_pip = find_best_pip(pips, arc);
|
let selected_pip = find_best_pip(pips, arc);
|
||||||
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
log_info!("split arc {} to {} horizontally across pip {}\n", ctx.name_of_wire(arc.get_source_wire()).to_str().unwrap(), ctx.name_of_wire(arc.get_sink_wire()).to_str().unwrap(), ctx.name_of_pip(selected_pip).to_str().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip);
|
let (src_to_pip, pip_to_dst) = arc.split(ctx, selected_pip);
|
||||||
let (seg1, seg2) = match (source_is_north, source_is_east) {
|
let (seg1, seg2) = match (source_is_north, source_is_east) {
|
||||||
(true, true) => (Segment::Northeast, Segment::Northwest),
|
(true, true) => (Segment::Northeast, Segment::Northwest),
|
||||||
@ -458,6 +488,10 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
let vert_pip = find_best_pip(pips, arc);
|
let vert_pip = find_best_pip(pips, arc);
|
||||||
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
explored_pips.fetch_add(pips.len(), std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
log_info!("split arc {} to {} across pips {} and {}\n", ctx.name_of_wire(arc.get_source_wire()).to_str().unwrap(), ctx.name_of_wire(arc.get_sink_wire()).to_str().unwrap(), ctx.name_of_pip(horiz_pip).to_str().unwrap(), ctx.name_of_pip(vert_pip).to_str().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
let horiz_loc: Coord = ctx.pip_location(horiz_pip).into();
|
let horiz_loc: Coord = ctx.pip_location(horiz_pip).into();
|
||||||
let horiz_is_east = horiz_loc.is_east_of(&partition_coords);
|
let horiz_is_east = horiz_loc.is_east_of(&partition_coords);
|
||||||
let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = if horiz_is_east == source_is_east {
|
let (src_to_mid1, mid1_to_mid2, mid2_to_dst) = if horiz_is_east == source_is_east {
|
||||||
@ -610,6 +644,7 @@ fn partition<R: RangeBounds<i32>>(
|
|||||||
|
|
||||||
pub fn find_partition_point_and_sanity_check(
|
pub fn find_partition_point_and_sanity_check(
|
||||||
ctx: &npnr::Context,
|
ctx: &npnr::Context,
|
||||||
|
nets: &npnr::Nets,
|
||||||
arcs: &[Arc],
|
arcs: &[Arc],
|
||||||
pips: &[npnr::PipId],
|
pips: &[npnr::PipId],
|
||||||
x_start: i32,
|
x_start: i32,
|
||||||
@ -618,7 +653,7 @@ pub fn find_partition_point_and_sanity_check(
|
|||||||
y_finish: i32,
|
y_finish: i32,
|
||||||
) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) {
|
) -> (i32, i32, Vec<Arc>, Vec<Arc>, Vec<Arc>, Vec<Arc>) {
|
||||||
let (x_part, y_part, ne, se, sw, nw) =
|
let (x_part, y_part, ne, se, sw, nw) =
|
||||||
find_partition_point(ctx, 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_ne = 0;
|
||||||
let mut invalid_arcs_in_se = 0;
|
let mut invalid_arcs_in_se = 0;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use std::collections::{BinaryHeap, HashMap};
|
use std::{collections::{BinaryHeap, HashMap}, time::Duration};
|
||||||
|
|
||||||
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
npnr::{self, NetIndex, PipId},
|
npnr::{self, NetIndex, PipId},
|
||||||
@ -64,6 +66,9 @@ impl Arc {
|
|||||||
pub fn get_sink_wire(&self) -> npnr::WireId {
|
pub fn get_sink_wire(&self) -> npnr::WireId {
|
||||||
self.sink_wire
|
self.sink_wire
|
||||||
}
|
}
|
||||||
|
pub fn net(&self) -> npnr::NetIndex {
|
||||||
|
self.net
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -118,34 +123,62 @@ impl Router {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn route(&mut self, ctx: &npnr::Context, arcs: &[Arc]) {
|
pub fn route(&mut self, ctx: &npnr::Context, nets: &npnr::Nets, arcs: &[Arc]) {
|
||||||
|
let progress = ProgressBar::new(arcs.len() as u64);
|
||||||
|
progress.set_style(
|
||||||
|
ProgressStyle::with_template("[{elapsed}] [{bar:40.magenta/red}] {msg:30!}")
|
||||||
|
.unwrap()
|
||||||
|
.progress_chars("━╸ "),
|
||||||
|
);
|
||||||
|
|
||||||
|
progress.enable_steady_tick(Duration::from_secs_f32(0.2));
|
||||||
for arc in arcs {
|
for arc in arcs {
|
||||||
self.route_arc(ctx, arc);
|
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();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
progress.finish_and_clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn route_arc(&mut self, ctx: &npnr::Context, arc: &Arc) {
|
fn route_arc(&mut self, ctx: &npnr::Context, nets: &npnr::Nets, arc: &Arc) {
|
||||||
let mut queue = BinaryHeap::new();
|
let mut queue = BinaryHeap::new();
|
||||||
let mut visited = HashMap::new();
|
let mut visited = HashMap::new();
|
||||||
|
|
||||||
queue.push(QueuedWire::new(0.0, 0.0, arc.source_wire));
|
queue.push(QueuedWire::new(0.0, 0.0, arc.source_wire));
|
||||||
visited.insert(arc.source_wire, npnr::PipId::null());
|
visited.insert(arc.source_wire, npnr::PipId::null());
|
||||||
|
|
||||||
|
let mut found_sink = false;
|
||||||
|
|
||||||
|
let name = ctx.name_of(nets.name_from_index(arc.net)).to_str().unwrap().to_string();
|
||||||
|
let verbose = name == "decode_to_execute_IS_RS2_SIGNED_LUT4_D_1_Z_CCU2C_B1_S0_CCU2C_S0_3_B1";
|
||||||
|
|
||||||
while let Some(source) = queue.pop() {
|
while let Some(source) = queue.pop() {
|
||||||
if source.wire == arc.sink_wire {
|
if source.wire == arc.sink_wire {
|
||||||
panic!("found the sink!");
|
found_sink = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
log_info!("{}:\n", ctx.name_of_wire(source.wire).to_str().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
for pip in ctx.get_downhill_pips(source.wire) {
|
for pip in ctx.get_downhill_pips(source.wire) {
|
||||||
let pip_loc = ctx.pip_location(pip);
|
/*let pip_loc = ctx.pip_location(pip);
|
||||||
let pip_coord = partition::Coord::from(pip_loc);
|
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) {
|
if pip_coord.is_north_of(&self.box_ne) || pip_coord.is_east_of(&self.box_ne) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if pip_coord.is_south_of(&self.box_sw) || pip_coord.is_west_of(&self.box_sw) {
|
if pip_coord.is_south_of(&self.box_sw) || pip_coord.is_west_of(&self.box_sw) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (!ctx->checkPipAvailForNet(dh, net))
|
if (!ctx->checkPipAvailForNet(dh, net))
|
||||||
@ -175,7 +208,7 @@ impl Router {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let driver = self.wire_driver.get(&sink);
|
/*let driver = self.wire_driver.get(&sink);
|
||||||
if let Some(&driver) = driver {
|
if let Some(&driver) = driver {
|
||||||
if driver != pip {
|
if driver != pip {
|
||||||
continue;
|
continue;
|
||||||
@ -183,10 +216,14 @@ impl Router {
|
|||||||
if *self.bound_pip.get(&driver).unwrap() != arc.net {
|
if *self.bound_pip.get(&driver).unwrap() != arc.net {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
visited.insert(sink, pip);
|
visited.insert(sink, pip);
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
log_info!(" {}\n", ctx.name_of_pip(pip).to_str().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
let delay =
|
let delay =
|
||||||
source.cost + ctx.pip_delay(pip) + ctx.wire_delay(sink) + ctx.delay_epsilon();
|
source.cost + ctx.pip_delay(pip) + ctx.wire_delay(sink) + ctx.delay_epsilon();
|
||||||
let qw = QueuedWire::new(delay, ctx.estimate_delay(sink, arc.sink_wire), sink);
|
let qw = QueuedWire::new(delay, ctx.estimate_delay(sink, arc.sink_wire), sink);
|
||||||
@ -194,16 +231,21 @@ impl Router {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
let mut wire = arc.sink_wire;
|
let mut wire = arc.sink_wire;
|
||||||
while wire != arc.source_wire {
|
while wire != arc.source_wire {
|
||||||
let pip = *visited.get(&wire).unwrap();
|
/*if verbose {
|
||||||
|
println!("Wire: {}", ctx.name_of_wire(wire).to_str().unwrap());
|
||||||
|
}*/
|
||||||
|
let pip = *visited.get(&wire).unwrap_or_else(|| panic!("Expected wire {} to have driving pip", ctx.name_of_wire(wire).to_str().unwrap()));
|
||||||
self.bind_pip(pip, arc.net);
|
self.bind_pip(pip, arc.net);
|
||||||
wire = ctx.pip_src_wire(pip);
|
wire = ctx.pip_src_wire(pip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_pip(&mut self, pip: PipId, net: NetIndex) {
|
fn bind_pip(&mut self, pip: PipId, net: NetIndex) {
|
||||||
assert!(!self.bound_pip.contains_key(&pip));
|
//assert!(!self.bound_pip.contains_key(&pip));
|
||||||
self.bound_pip.insert(pip, net);
|
self.bound_pip.insert(pip, net);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user