make partitioner handle arcs with no locations

This commit is contained in:
SpaceCat-Chan 2023-03-11 13:51:32 +01:00 committed by Lofty
parent da2892fc28
commit 0bc945fbc3
5 changed files with 402 additions and 297 deletions

56
Cargo.lock generated
View File

@ -24,6 +24,7 @@ name = "awooter"
version = "0.1.0"
dependencies = [
"colored",
"enumflags2",
"indicatif",
"itertools",
"libc",
@ -116,6 +117,26 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "enumflags2"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb"
dependencies = [
"enumflags2_derive",
]
[[package]]
name = "enumflags2_derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -190,6 +211,24 @@ version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15eb2c6e362923af47e13c23ca5afb859e83d54452c55b0b9ac763b8f7c1ac16"
[[package]]
name = "proc-macro2"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.6.0"
@ -219,6 +258,17 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "terminal_size"
version = "0.1.17"
@ -229,6 +279,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-width"
version = "0.1.10"

View File

@ -15,4 +15,5 @@ libc = "0.2"
indicatif = { version = "0.17", features = ["rayon"] }
rayon = "1.6"
colored = "2"
itertools = "0.10.5"
itertools = "0.10.5"
enumflags2 = "0.7.5"

View File

@ -61,9 +61,9 @@ fn extract_arcs_from_nets(ctx: &npnr::Context, nets: &npnr::Nets) -> Vec<route::
for sink_wire in ctx.sink_wires(net, *sink_ref) {
arcs.push(route::Arc::new(
source_wire,
source,
Some(source),
sink_wire,
sink,
Some(sink),
net.index(),
nets.name_from_index(net.index()),
));

View File

@ -5,6 +5,7 @@ use std::{
};
use colored::Colorize;
use enumflags2::{bitflags, BitFlags};
use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle};
use itertools::Itertools;
use rayon::prelude::*;
@ -14,12 +15,52 @@ use crate::{
route::Arc,
};
#[bitflags]
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Quadrant {
Northeast,
Southeast,
Southwest,
Northwest,
Northeast = 1,
Southeast = 2,
Southwest = 8,
Northwest = 4,
}
impl Quadrant {
fn flip_east_west(self) -> Self {
match self {
Self::Northeast => Self::Northwest,
Self::Northwest => Self::Northeast,
Self::Southeast => Self::Southwest,
Self::Southwest => Self::Southeast,
}
}
fn flip_north_south(self) -> Self {
match self {
Self::Northeast => Self::Southeast,
Self::Northwest => Self::Southwest,
Self::Southeast => Self::Northeast,
Self::Southwest => Self::Northwest,
}
}
fn flip_diagonal(self) -> Self {
match self {
Self::Northeast => Self::Southwest,
Self::Northwest => Self::Southeast,
Self::Southeast => Self::Northwest,
Self::Southwest => Self::Northeast,
}
}
}
// manual bit fiddling because using .iter().map().collect() compiles down to a loop
fn flip_quads_north_south(q: BitFlags<Quadrant>) -> BitFlags<Quadrant> {
BitFlags::from_bits((q.bits() & 0b1010) >> 1 | (q.bits() & 0b0101) << 1).unwrap()
}
fn flip_quads_east_west(q: BitFlags<Quadrant>) -> BitFlags<Quadrant> {
BitFlags::from_bits((q.bits() & 0b1100) >> 2 | (q.bits() & 0b0011) << 2).unwrap()
}
fn flip_quads_diagonal(q: BitFlags<Quadrant>) -> BitFlags<Quadrant> {
BitFlags::from_bits(q.bits().reverse_bits() >> 4).unwrap()
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -182,6 +223,7 @@ impl From<npnr::Loc> for Coord {
}
}
}
impl Into<npnr::Loc> for Coord {
fn into(self) -> npnr::Loc {
npnr::Loc {
@ -192,6 +234,78 @@ impl Into<npnr::Loc> for Coord {
}
}
struct SegmentedArc {
arc: Arc,
source_quads: BitFlags<Quadrant>,
estimated_source_location: Coord,
sink_quads: BitFlags<Quadrant>,
estimated_sink_location: Coord,
}
impl SegmentedArc {
fn new(arc: Arc, partition_point: &Coord, ctx: &npnr::Context) -> Self {
let (source_quads, sum_source_pos, source_count) = if let Some(src) = arc.get_source_loc() {
let src: Coord = src.into();
(src.segment_from(partition_point).into(), src, 1)
} else {
ctx.get_uphill_pips(arc.source_wire())
.map(|pip| {
let c: Coord = ctx.pip_location(pip).into();
c
})
.fold(
(BitFlags::empty(), Coord::new(0, 0), 0),
|(quads, pos, count), c| {
(
quads | c.segment_from(partition_point),
Coord::new(pos.x + c.x, pos.y + c.y),
count + 1,
)
},
)
};
let (sink_quads, sum_sink_pos, sink_count) = if let Some(sink) = arc.get_sink_loc() {
let sink: Coord = sink.into();
(sink.segment_from(partition_point).into(), sink, 1)
} else {
ctx.get_downhill_pips(arc.sink_wire())
.map(|pip| {
let c: Coord = ctx.pip_location(pip).into();
c
})
.fold(
(BitFlags::empty(), Coord::new(0, 0), 0),
|(quads, pos, count), c| {
(
quads | c.segment_from(partition_point),
Coord::new(pos.x + c.x, pos.y + c.y),
count + 1,
)
},
)
};
assert!(
source_count != 0 && sink_count != 0,
"absolutely unroutable arc found"
);
Self {
arc,
source_quads,
estimated_source_location: Coord::new(
sum_source_pos.x / source_count,
sum_source_pos.y / source_count,
),
sink_quads,
estimated_sink_location: Coord::new(
sum_sink_pos.x / sink_count,
sum_sink_pos.y / sink_count,
),
}
}
}
pub fn find_partition_point(
ctx: &npnr::Context,
nets: &npnr::Nets,
@ -207,8 +321,14 @@ pub fn find_partition_point(
let mut x_diff = 0; //(x_finish - x_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?
while x_diff != 0 {
let (ne, se, sw, nw) = approximate_partition_results(arcs, (x, y));
let segmented_arcs = arcs
.iter()
.map(|arc| SegmentedArc::new(arc.clone(), &Coord::new(x, y), ctx))
.collect::<Vec<_>>();
let (ne, se, sw, nw) = approximate_partition_results(&segmented_arcs[..], (x, y));
let north = ne + nw;
let south = se + sw;
@ -244,10 +364,15 @@ pub fn find_partition_point(
y_diff >>= 1;
}
let segmented_arcs = arcs
.iter()
.map(|arc| SegmentedArc::new(arc.clone(), &Coord::new(x, y), ctx))
.collect::<Vec<_>>();
let (ne, se, sw, nw, special) = partition(
ctx,
nets,
arcs,
&segmented_arcs[..],
pips,
x,
y,
@ -273,7 +398,7 @@ pub fn find_partition_point(
}
fn approximate_partition_results(
arcs: &[Arc],
arcs: &[SegmentedArc],
partition_point: (i32, i32),
) -> (usize, usize, usize, usize) {
let mut count_ne = 0;
@ -282,66 +407,66 @@ fn approximate_partition_results(
let mut count_nw = 0;
for arc in arcs {
// TODO(SpaceCat~Chan): stop being lazy and merge Loc and Coord already
let source_is_north = arc.get_source_loc().x < partition_point.0;
let source_is_east = arc.get_source_loc().y < partition_point.1;
let sink_is_north = arc.get_sink_loc().x < partition_point.0;
let sink_is_east = arc.get_sink_loc().y < partition_point.1;
if source_is_north == sink_is_north && source_is_east == sink_is_east {
match (source_is_north, source_is_east) {
(true, true) => count_ne += 1,
(false, true) => count_se += 1,
(false, false) => count_sw += 1,
(true, false) => count_nw += 1,
if !(arc.source_quads & arc.sink_quads).is_empty() {
match (arc.source_quads & arc.sink_quads).iter().next().unwrap() {
Quadrant::Northeast => count_ne += 1,
Quadrant::Southeast => count_se += 1,
Quadrant::Southwest => count_sw += 1,
Quadrant::Northwest => count_nw += 1,
}
} else if source_is_north != sink_is_north && source_is_east == sink_is_east {
if source_is_east {
count_ne += 1;
count_se += 1;
} else {
count_nw += 1;
count_sw += 1;
} else if !(flip_quads_north_south(arc.source_quads) & arc.sink_quads).is_empty() {
match (flip_quads_north_south(arc.source_quads) & arc.sink_quads)
.iter()
.next()
.unwrap()
{
Quadrant::Northeast | Quadrant::Southeast => {
count_ne += 1;
count_se += 1;
}
Quadrant::Northwest | Quadrant::Southwest => {
count_nw += 1;
count_sw += 1;
}
}
} else if source_is_north == sink_is_north {
if source_is_north {
count_ne += 1;
count_nw += 1;
} else {
count_se += 1;
count_sw += 1;
} else if !(flip_quads_east_west(arc.source_quads) & arc.sink_quads).is_empty() {
match (flip_quads_east_west(arc.source_quads) & arc.sink_quads)
.iter()
.next()
.unwrap()
{
Quadrant::Northeast | Quadrant::Northwest => {
count_ne += 1;
count_nw += 1;
}
Quadrant::Southeast | Quadrant::Southwest => {
count_se += 1;
count_sw += 1;
}
}
} else {
// all of this calculation is not be needed and an approximation would be good enough
// but i can't be bothered (yes this is all copy-pasted from the actual partitioner)
let mut middle_horiz = (
let middle_horiz = (
partition_point.0,
split_line_over_x(
(arc.get_source_loc(), arc.get_sink_loc()),
(arc.estimated_source_location, arc.estimated_sink_location),
partition_point.0,
),
);
let mut middle_vert = (
split_line_over_y(
(arc.get_source_loc(), arc.get_sink_loc()),
partition_point.1,
),
partition_point.1,
);
// need to avoid the partition point
if middle_horiz.1 == partition_point.1 || middle_vert.0 == partition_point.0 {
if source_is_east != sink_is_north {
middle_horiz.1 = partition_point.1 + 1;
middle_vert.0 = partition_point.0 - 1;
} else {
middle_horiz.1 = partition_point.1 + 1;
middle_vert.0 = partition_point.0 + 1;
}
}
let horiz_happens_first = (middle_horiz.1 < partition_point.1) == source_is_east;
let seg1 = (flip_quads_diagonal(arc.source_quads) & arc.sink_quads)
.iter()
.next()
.unwrap();
let horiz_happens_first = (middle_horiz.1 < partition_point.1)
== matches!(seg1, Quadrant::Northeast | Quadrant::Southeast);
// note: if you invert all the bools it adds to the same things, not sure how make less redundant
match (source_is_north, source_is_east, horiz_happens_first) {
match (
matches!(seg1, Quadrant::Northeast | Quadrant::Northwest),
matches!(seg1, Quadrant::Northeast | Quadrant::Southeast),
horiz_happens_first,
) {
(true, true, true) => {
count_ne += 1;
count_se += 1;
@ -392,7 +517,7 @@ fn approximate_partition_results(
/// finds the y location a line would be split at if you split it at a certain x location
///
/// the function assumes the line goes on forever in both directions, and it truncates the actual coordinate
fn split_line_over_x(line: (npnr::Loc, npnr::Loc), x_location: i32) -> i32 {
fn split_line_over_x(line: (Coord, Coord), x_location: i32) -> i32 {
if line.0.x == line.1.x {
// the line is a straight line in the direction, there is either infinite solutions, or none
// we simply average the y coordinate to give a "best effort" guess
@ -407,20 +532,12 @@ fn split_line_over_x(line: (npnr::Loc, npnr::Loc), x_location: i32) -> i32 {
}
/// finds the x location a line would be split at if you split it at a certain y location, assuming the line goes on forever in both directions
fn split_line_over_y(line: (npnr::Loc, npnr::Loc), y_location: i32) -> i32 {
fn split_line_over_y(line: (Coord, Coord), y_location: i32) -> i32 {
// laziness supreme!
split_line_over_x(
(
npnr::Loc {
x: line.0.y,
y: line.0.x,
z: 0,
},
npnr::Loc {
x: line.1.y,
y: line.1.x,
z: 0,
},
Coord::new(line.0.y, line.0.x),
Coord::new(line.1.y, line.1.x),
),
y_location,
)
@ -430,7 +547,7 @@ fn split_line_over_y(line: (npnr::Loc, npnr::Loc), y_location: i32) -> i32 {
fn partition(
ctx: &npnr::Context,
nets: &npnr::Nets,
arcs: &[Arc],
arcs: &[SegmentedArc],
pips: &[npnr::PipId],
x: i32,
y: i32,
@ -474,8 +591,6 @@ fn partition(
progress.set_message(format!("overused wires: {}", overused_wires));
let mut bad_nets = std::collections::HashSet::new();
let _is_general_routing = |wire: &str| {
wire.contains("H00")
|| wire.contains("V00")
@ -487,72 +602,28 @@ fn partition(
|| wire.contains("V06")
};
for arc in arcs {
if bad_nets.contains(&arc.net()) {
continue;
}
let source_loc = arc.get_source_loc();
let source_coords: Coord = source_loc.into();
let sink_loc = arc.get_sink_loc();
let sink_coords: Coord = sink_loc.into();
// test for annoying special case
let mut have_any_in_same_segment = false;
for pip in ctx.get_downhill_pips(arc.source_wire()) {
let pip_coord: Coord = ctx.pip_location(pip).into();
let pip_seg = pip_coord.segment_from(&partition_coords);
have_any_in_same_segment |= pip_seg == source_coords.segment_from(&partition_coords)
}
if !have_any_in_same_segment {
bad_nets.insert(arc.net());
}
let mut have_any_in_same_segment = false;
for pip in ctx.get_uphill_pips(arc.sink_wire()) {
let pip_coord: Coord = ctx.pip_location(pip).into();
let pip_seg = pip_coord.segment_from(&partition_coords);
have_any_in_same_segment |= pip_seg == sink_coords.segment_from(&partition_coords)
}
if !have_any_in_same_segment {
bad_nets.insert(arc.net());
}
}
let arcs = arcs
.into_par_iter()
.progress_with(progress)
.flat_map(|arc| {
let raw_net = nets.net_from_index(arc.net());
let source_loc = arc.get_source_loc();
let source_coords: Coord = source_loc.into();
let source_is_north = source_coords.is_north_of(&partition_coords);
let source_is_east = source_coords.is_east_of(&partition_coords);
let sink_loc = arc.get_sink_loc();
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 raw_net = nets.net_from_index(arc.arc.net());
let _name = ctx
.name_of(nets.name_from_index(arc.net()))
.name_of(nets.name_from_index(arc.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 bad_nets.contains(&arc.net()) {
special.lock().unwrap().push(arc.clone());
return vec![];
}
if !(arc.source_quads & arc.sink_quads).is_empty() {
let seg = (arc.source_quads & arc.sink_quads).iter().next().unwrap();
vec![(seg, arc.arc.clone())]
} else if !(arc.source_quads & flip_quads_north_south(arc.sink_quads)).is_empty() {
let seg1 = (arc.source_quads & flip_quads_north_south(arc.sink_quads))
.iter()
.next()
.unwrap();
let seg2 = seg1.flip_north_south();
if source_is_north == sink_is_north && source_is_east == sink_is_east {
let seg = source_coords.segment_from(&partition_coords);
vec![(seg, arc.clone())]
} else if source_is_north != sink_is_north && source_is_east == sink_is_east {
let (seg1, seg2) = match (source_is_north, source_is_east) {
(true, true) => (Quadrant::Northeast, Quadrant::Southeast),
(true, false) => (Quadrant::Northwest, Quadrant::Southwest),
(false, true) => (Quadrant::Southeast, Quadrant::Northeast),
(false, false) => (Quadrant::Southwest, Quadrant::Northwest),
};
if let Some(partition) = partition_single_arc(
ctx,
&pip_selector,
@ -565,32 +636,8 @@ fn partition(
) {
partition
} else {
let (seg1, seg2, seg3, seg4) = match (source_is_north, source_is_east) {
(true, true) => (
Quadrant::Northeast,
Quadrant::Northwest,
Quadrant::Southwest,
Quadrant::Southeast,
),
(true, false) => (
Quadrant::Northwest,
Quadrant::Northeast,
Quadrant::Southeast,
Quadrant::Southwest,
),
(false, true) => (
Quadrant::Southeast,
Quadrant::Southwest,
Quadrant::Northwest,
Quadrant::Northeast,
),
(false, false) => (
Quadrant::Southwest,
Quadrant::Southeast,
Quadrant::Northeast,
Quadrant::Northwest,
),
};
let (seg2, seg3, seg4) =
(seg1.flip_east_west(), seg2.flip_east_west(), seg2);
partition_single_arc(
ctx,
&pip_selector,
@ -603,13 +650,12 @@ fn partition(
)
.expect("failed to partition arc on NorthSouth axis")
}
} else if source_is_north == sink_is_north && source_is_east != sink_is_east {
let (seg1, seg2) = match (source_is_north, source_is_east) {
(true, true) => (Quadrant::Northeast, Quadrant::Northwest),
(true, false) => (Quadrant::Northwest, Quadrant::Northeast),
(false, true) => (Quadrant::Southeast, Quadrant::Southwest),
(false, false) => (Quadrant::Southwest, Quadrant::Southeast),
};
} else if !(arc.source_quads & flip_quads_east_west(arc.sink_quads)).is_empty() {
let seg1 = (arc.source_quads & flip_quads_east_west(arc.sink_quads))
.iter()
.next()
.unwrap();
let seg2 = seg1.flip_east_west();
if let Some(partition) = partition_single_arc(
ctx,
&pip_selector,
@ -622,32 +668,8 @@ fn partition(
) {
partition
} else {
let (seg1, seg2, seg3, seg4) = match (source_is_north, source_is_east) {
(true, true) => (
Quadrant::Northeast,
Quadrant::Southeast,
Quadrant::Southwest,
Quadrant::Northwest,
),
(true, false) => (
Quadrant::Northwest,
Quadrant::Southwest,
Quadrant::Southeast,
Quadrant::Northeast,
),
(false, true) => (
Quadrant::Southeast,
Quadrant::Northeast,
Quadrant::Northwest,
Quadrant::Southwest,
),
(false, false) => (
Quadrant::Southwest,
Quadrant::Northwest,
Quadrant::Northeast,
Quadrant::Southeast,
),
};
let (seg2, seg3, seg4) =
(seg1.flip_north_south(), seg2.flip_north_south(), seg2);
partition_single_arc(
ctx,
&pip_selector,
@ -661,56 +683,31 @@ fn partition(
.expect("failed to partition arc on EastWest axis")
}
} else {
let middle_horiz = (x, split_line_over_x((source_loc, sink_loc), x));
let horiz_happens_first = (middle_horiz.1 < y) == source_is_east;
let middle_horiz = (
x,
split_line_over_x(
(arc.estimated_source_location, arc.estimated_sink_location),
x,
),
);
let seg1 = (arc.source_quads & flip_quads_diagonal(arc.sink_quads))
.iter()
.next()
.unwrap();
let horiz_happens_first = (middle_horiz.1 < y)
== matches!(seg1, Quadrant::Northeast | Quadrant::Southeast);
let (seg2, seg3) = (
if horiz_happens_first {
seg1.flip_east_west()
} else {
seg1.flip_north_south()
},
seg1.flip_diagonal(),
);
let grab_segment_order = |horiz_happens_first| match (
source_is_north,
source_is_east,
horiz_happens_first,
) {
(true, true, true) => (
Quadrant::Northeast,
Quadrant::Southeast,
Quadrant::Southwest,
),
(true, false, true) => (
Quadrant::Northwest,
Quadrant::Southwest,
Quadrant::Southeast,
),
(false, true, true) => (
Quadrant::Southeast,
Quadrant::Northeast,
Quadrant::Northwest,
),
(false, false, true) => (
Quadrant::Southwest,
Quadrant::Northwest,
Quadrant::Northeast,
),
(true, true, false) => (
Quadrant::Northeast,
Quadrant::Northwest,
Quadrant::Southwest,
),
(true, false, false) => (
Quadrant::Northwest,
Quadrant::Northeast,
Quadrant::Southeast,
),
(false, true, false) => (
Quadrant::Southeast,
Quadrant::Southwest,
Quadrant::Northwest,
),
(false, false, false) => (
Quadrant::Southwest,
Quadrant::Southeast,
Quadrant::Northeast,
),
};
let (seg1, seg2, seg3) = grab_segment_order(horiz_happens_first);
if let Some(partition) = partition_single_arc(
ctx,
&pip_selector,
@ -723,8 +720,8 @@ fn partition(
) {
partition
} else {
// flip `horiz_happens_first` and hope for the best
let (seg1, seg2, seg3) = grab_segment_order(!horiz_happens_first);
// go other way around
let seg2 = seg2.flip_diagonal();
partition_single_arc(
ctx,
&pip_selector,
@ -861,16 +858,17 @@ fn partition(
fn partition_single_arc(
ctx: &npnr::Context,
pip_selector: &PipSelector,
arc: &Arc,
arc: &SegmentedArc,
raw_net: *mut npnr::NetInfo,
partition_point: Coord,
min_bounds: &Coord,
max_bounds: &Coord,
segments: &[Quadrant],
) -> Option<Vec<(Quadrant, Arc)>> {
let start_coord: Coord = arc.get_source_loc().into();
let end_coord: Coord = arc.get_sink_loc().into();
let mut current_arc = arc.clone();
let start_coord: Coord = arc.estimated_source_location;
let end_coord: Coord = arc.estimated_sink_location;
let mut current_coming_from = start_coord;
let mut current_arc = arc.arc.clone();
let mut arcs = vec![];
for (from_quad, to_quad) in segments.iter().tuple_windows() {
let direction = Direction::between(*from_quad, *to_quad).unwrap();
@ -880,14 +878,39 @@ fn partition_single_arc(
let pip = pip_selector.find_pip(
ctx,
intersection.into(),
current_arc.get_source_loc(),
current_coming_from.into(),
current_arc.net(),
raw_net,
)?;
current_coming_from = ctx.pip_location(pip).into();
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));
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));
Some(arcs)
}
@ -922,83 +945,107 @@ pub fn find_partition_point_and_sanity_check(
println!("\nne:");
for arc in &ne {
if arc.get_source_loc().x > x_part
|| arc.get_source_loc().y > y_part
|| arc.get_sink_loc().x > x_part
|| arc.get_sink_loc().y > y_part
if arc.get_source_loc().map(|v| v.x > x_part).unwrap_or(false)
|| arc.get_source_loc().map(|v| v.y > y_part).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.x > x_part).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.y > y_part).unwrap_or(false)
{
invalid_arcs_in_ne += 1;
}
if arc.get_source_loc().x <= x_start
|| arc.get_source_loc().y <= y_start
|| arc.get_sink_loc().x <= x_start
|| arc.get_sink_loc().y <= y_start
if arc
.get_source_loc()
.map(|v| v.x <= x_start)
.unwrap_or(false)
|| arc
.get_source_loc()
.map(|v| v.y <= y_start)
.unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.x <= x_start).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.y <= y_start).unwrap_or(false)
{
println!(
"oob: {:?} -> {:?}",
arc.get_source_loc(),
arc.get_sink_loc()
);
//println!(
// "oob: {:?} -> {:?}",
// arc.get_source_loc(),
// arc.get_sink_loc()
//);
out_of_bound_arcs_in_ne += 1;
}
}
println!("\nse:");
for arc in &se {
if arc.get_source_loc().x < x_part
|| arc.get_source_loc().y > y_part
|| arc.get_sink_loc().x < x_part
|| arc.get_sink_loc().y > y_part
if arc.get_source_loc().map(|v| v.x < x_part).unwrap_or(false)
|| arc.get_source_loc().map(|v| v.y > y_part).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.x < x_part).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.y > y_part).unwrap_or(false)
{
invalid_arcs_in_se += 1;
}
if arc.get_source_loc().x >= x_finish
|| arc.get_source_loc().y <= y_start
|| arc.get_sink_loc().x >= x_finish
|| arc.get_sink_loc().y <= y_start
if arc
.get_source_loc()
.map(|v| v.x >= x_finish)
.unwrap_or(false)
|| arc
.get_source_loc()
.map(|v| v.y <= y_start)
.unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.x >= x_finish).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.y <= y_start).unwrap_or(false)
{
println!(
"oob: {:?} -> {:?}",
arc.get_source_loc(),
arc.get_sink_loc()
);
//println!(
// "oob: {:?} -> {:?}",
// arc.get_source_loc(),
// arc.get_sink_loc()
//);
out_of_bound_arcs_in_se += 1;
}
}
println!("\nsw:");
for arc in &sw {
if arc.get_source_loc().x < x_part
|| arc.get_source_loc().y < y_part
|| arc.get_sink_loc().x < x_part
|| arc.get_sink_loc().y < y_part
if arc.get_source_loc().map(|v| v.x < x_part).unwrap_or(false)
|| arc.get_source_loc().map(|v| v.y < y_part).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.x < x_part).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.y < y_part).unwrap_or(false)
{
invalid_arcs_in_sw += 1;
}
if arc.get_source_loc().x >= x_finish
|| arc.get_source_loc().y >= y_finish
|| arc.get_sink_loc().x >= x_finish
|| arc.get_sink_loc().y >= y_finish
if arc
.get_source_loc()
.map(|v| v.x >= x_finish)
.unwrap_or(false)
|| arc
.get_source_loc()
.map(|v| v.y >= y_finish)
.unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.x >= x_finish).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.y >= y_finish).unwrap_or(false)
{
println!(
"oob: {:?} -> {:?}",
arc.get_source_loc(),
arc.get_sink_loc()
);
//println!(
// "oob: {:?} -> {:?}",
// arc.get_source_loc(),
// arc.get_sink_loc()
//);
out_of_bound_arcs_in_sw += 1;
}
}
println!("\nnw:");
for arc in &nw {
if arc.get_source_loc().x > x_part
|| arc.get_source_loc().y < y_part
|| arc.get_sink_loc().x > x_part
|| arc.get_sink_loc().y < y_part
if arc.get_source_loc().map(|v| v.x > x_part).unwrap_or(false)
|| arc.get_source_loc().map(|v| v.y < y_part).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.x > x_part).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.y < y_part).unwrap_or(false)
{
invalid_arcs_in_nw += 1;
}
if arc.get_source_loc().x <= x_start
|| arc.get_source_loc().y >= y_finish
|| arc.get_sink_loc().x <= x_start
|| arc.get_sink_loc().y >= y_finish
if arc
.get_source_loc()
.map(|v| v.x <= x_start)
.unwrap_or(false)
|| arc
.get_source_loc()
.map(|v| v.y >= y_finish)
.unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.x <= x_start).unwrap_or(false)
|| arc.get_sink_loc().map(|v| v.y >= y_finish).unwrap_or(false)
{
println!(
"oob: {:?} -> {:?}",

View File

@ -16,9 +16,9 @@ use crate::{
#[derive(Clone, Hash, PartialEq, Eq)]
pub struct Arc {
source_wire: WireId,
source_loc: Loc,
source_loc: Option<Loc>,
sink_wire: WireId,
sink_loc: Loc,
sink_loc: Option<Loc>,
net: NetIndex,
name: IdString,
}
@ -26,9 +26,9 @@ pub struct Arc {
impl Arc {
pub fn new(
source_wire: WireId,
source_loc: Loc,
source_loc: Option<Loc>,
sink_wire: WireId,
sink_loc: Loc,
sink_loc: Option<Loc>,
net: NetIndex,
name: IdString,
) -> Self {
@ -43,6 +43,7 @@ impl Arc {
}
pub fn split(&self, ctx: &npnr::Context, pip: npnr::PipId) -> (Self, Self) {
// should this still set the sink and source using the pip? not sure
let pip_src = ctx.pip_src_wire(pip);
let pip_dst = ctx.pip_dst_wire(pip);
(
@ -50,13 +51,13 @@ impl Arc {
source_wire: self.source_wire,
source_loc: self.source_loc,
sink_wire: pip_src,
sink_loc: ctx.pip_location(pip),
sink_loc: Some(ctx.pip_location(pip)),
net: self.net,
name: self.name,
},
Self {
source_wire: pip_dst,
source_loc: ctx.pip_location(pip),
source_loc: Some(ctx.pip_location(pip)),
sink_wire: self.sink_wire,
sink_loc: self.sink_loc,
net: self.net,
@ -74,10 +75,10 @@ impl Arc {
pub fn net(&self) -> npnr::NetIndex {
self.net
}
pub fn get_source_loc(&self) -> Loc {
pub fn get_source_loc(&self) -> Option<Loc> {
self.source_loc
}
pub fn get_sink_loc(&self) -> Loc {
pub fn get_sink_loc(&self) -> Option<Loc> {
self.sink_loc
}
}