awooter: wire storage and some cleanup

This commit is contained in:
Lofty 2022-11-23 23:55:33 +00:00
parent 153c8a9c6c
commit 95e802ee3d
3 changed files with 50 additions and 47 deletions

View File

@ -126,6 +126,19 @@ extern "C" {
float npnr_context_estimate_delay(const Context *const ctx, uint64_t src, uint64_t dst) { return ctx->getDelayNS(ctx->estimateDelay(unwrap_wire(src), unwrap_wire(dst))); } float npnr_context_estimate_delay(const Context *const ctx, uint64_t src, uint64_t dst) { return ctx->getDelayNS(ctx->estimateDelay(unwrap_wire(src), unwrap_wire(dst))); }
float npnr_context_delay_epsilon(const Context *const ctx) { return ctx->getDelayNS(ctx->getDelayEpsilon()); } float npnr_context_delay_epsilon(const Context *const ctx) { return ctx->getDelayNS(ctx->getDelayEpsilon()); }
uint64_t npnr_context_get_wires_leak(const Context *const ctx, WireId **wires) {
auto wire_vec = std::vector<WireId>{};
for (auto wire : ctx->getWires()) {
wire_vec.push_back(wire);
}
wire_vec.shrink_to_fit();
auto size = wire_vec.size();
*wires = wire_vec.data();
// Yes, by placement-newing over `wire_vec` we leak memory.
new (&wire_vec) std::vector<WireId>;
return size;
}
void npnr_context_check(const Context *const ctx) { ctx->check(); } void npnr_context_check(const Context *const ctx) { ctx->check(); }
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(); }
@ -158,33 +171,6 @@ extern "C" {
return size; return size;
} }
// Yes, this is quadratic. It gets imported once and then never worried about again.
// There are bigger fish to fry.
int npnr_context_nets_key(const Context *const ctx, uint32_t n) {
if (ctx == nullptr) {
return 0;
}
for (auto& item : ctx->nets) {
if (n == 0) {
return item.first.hash();
}
n--;
}
return 0;
}
NetInfo* npnr_context_nets_value(const Context *const ctx, uint32_t n) {
if (ctx == nullptr) {
return nullptr;
}
for (auto& item : ctx->nets) {
if (n == 0) {
return item.second.get();
}
n--;
}
return nullptr;
}
PortRef* npnr_netinfo_driver(NetInfo *const net) { PortRef* npnr_netinfo_driver(NetInfo *const net) {
if (net == nullptr) { if (net == nullptr) {
return nullptr; return nullptr;
@ -221,8 +207,6 @@ extern "C" {
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
bool router_awooter(Context *ctx) { bool router_awooter(Context *ctx) {
static_assert(std::is_standard_layout<IdString>::value == true, "IdString is not FFI-safe");
log_info("Running Awooter...\n"); log_info("Running Awooter...\n");
auto result = npnr_router_awooter(ctx); auto result = npnr_router_awooter(ctx);
log_info("Router returned: %d\n", result); log_info("Router returned: %d\n", result);

View File

@ -212,6 +212,9 @@ fn route(ctx: &mut npnr::Context) -> bool {
ctx.grid_dim_y() ctx.grid_dim_y()
); );
let wires = npnr::Wires::new(ctx);
log_info!("Found {} wires\n", wires.len());
let nets = npnr::Nets::new(ctx); let nets = npnr::Nets::new(ctx);
log_info!("Found {} nets\n", nets.len()); log_info!("Found {} nets\n", nets.len());
@ -301,6 +304,8 @@ fn route(ctx: &mut npnr::Context) -> bool {
log_info!("=== level 1:\n"); log_info!("=== level 1:\n");
let (x, y, ne, se, sw, nw) = find_partition_point(&arcs, x_start, x_finish, y_start, y_finish); let (x, y, ne, se, sw, nw) = find_partition_point(&arcs, x_start, x_finish, y_start, y_finish);
todo!("figure out how to tell if a wire crosses the calculated partition boundaries");
/*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);
log_info!("=== level 2 SE:\n"); log_info!("=== level 2 SE:\n");

View File

@ -1,4 +1,5 @@
use std::{ffi::CStr, collections::{HashMap}, ptr::{NonNull}, marker::PhantomData}; use core::slice;
use std::{ffi::CStr, collections::{HashMap}, marker::PhantomData};
use libc::c_char; use libc::c_char;
@ -69,9 +70,7 @@ pub struct IdString(libc::c_int);
/// A type representing a bel name. /// A type representing a bel name.
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)] #[repr(transparent)]
pub struct BelId { pub struct BelId(u64);
_private: u64,
}
impl BelId { impl BelId {
/// Return a sentinel value that represents an invalid bel. /// Return a sentinel value that represents an invalid bel.
@ -88,9 +87,7 @@ impl BelId {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(transparent)] #[repr(transparent)]
pub struct PipId { pub struct PipId(u64);
_private: u64,
}
impl PipId { impl PipId {
pub fn null() -> Self { pub fn null() -> Self {
@ -256,6 +253,7 @@ extern "C" {
fn npnr_context_get_pip_src_wire(ctx: *const Context, pip: PipId) -> WireId; fn npnr_context_get_pip_src_wire(ctx: *const Context, pip: PipId) -> WireId;
fn npnr_context_get_pip_dst_wire(ctx: *const Context, pip: PipId) -> WireId; fn npnr_context_get_pip_dst_wire(ctx: *const Context, pip: PipId) -> WireId;
fn npnr_context_estimate_delay(ctx: *const Context, src: WireId, dst: WireId) -> libc::c_float; fn npnr_context_estimate_delay(ctx: *const Context, src: WireId, dst: WireId) -> libc::c_float;
fn npnr_context_get_wires_leak(ctx: *const Context, wires: *mut *mut WireId) -> u64;
fn npnr_context_check(ctx: *const Context); fn npnr_context_check(ctx: *const Context);
fn npnr_context_debug(ctx: *const Context) -> bool; fn npnr_context_debug(ctx: *const Context) -> bool;
@ -284,9 +282,7 @@ extern "C" {
/// Store for the users of a net. /// Store for the users of a net.
pub struct NetUsers<'a> { pub struct NetUsers<'a> {
users: NonNull<*mut PortRef>, users: &'a [*mut PortRef],
size: u32,
_data: PhantomData<&'a NetInfo>,
} }
impl<'a> NetUsers<'a> { impl<'a> NetUsers<'a> {
@ -294,9 +290,9 @@ impl<'a> NetUsers<'a> {
let mut users = std::ptr::null_mut(); let mut users = std::ptr::null_mut();
// SAFETY: net is not null because it's a &mut, and users is only written to. // SAFETY: net is not null because it's a &mut, and users is only written to.
// Leaking memory is the most convenient FFI I could think of. // Leaking memory is the most convenient FFI I could think of.
let size = unsafe { npnr_netinfo_users_leak(net, &mut users as *mut *mut *mut PortRef) }; let len = unsafe { npnr_netinfo_users_leak(net, &mut users as *mut *mut *mut PortRef) };
let users = unsafe { NonNull::new_unchecked(users) }; let users = unsafe { slice::from_raw_parts(users, len as usize) };
Self { users, size, _data: PhantomData } Self { users }
} }
pub fn iter(&self) -> NetUsersIter<'_> { pub fn iter(&self) -> NetUsersIter<'_> {
@ -306,17 +302,14 @@ impl<'a> NetUsers<'a> {
pub struct NetUsersIter<'a> { pub struct NetUsersIter<'a> {
users: &'a NetUsers<'a>, users: &'a NetUsers<'a>,
n: u32, n: usize,
} }
impl Iterator for NetUsersIter<'_> { impl Iterator for NetUsersIter<'_> {
type Item = *mut PortRef; type Item = *mut PortRef;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.n >= self.users.size { let user = *self.users.users.get(self.n)?;
return None;
}
let user = unsafe { *self.users.users.as_ptr().add(self.n as usize) };
self.n += 1; self.n += 1;
Some(user) Some(user)
} }
@ -389,6 +382,27 @@ impl<'a> Iterator for NetSinkWireIter<'a> {
} }
} }
pub struct Wires<'a> {
wires: &'a [WireId],
}
impl<'a> Wires<'a> {
pub fn new(ctx: &'a Context) -> Wires<'a> {
let mut wires = std::ptr::null_mut();
let len = unsafe { npnr_context_get_wires_leak(ctx, &mut wires as *mut *mut WireId) };
let wires = unsafe { std::slice::from_raw_parts(wires, len as usize) };
Self { wires }
}
pub fn len(&self) -> usize {
self.wires.len()
}
pub fn iter(&self) -> impl Iterator<Item=&WireId> {
self.wires.iter()
}
}
macro_rules! log_info { macro_rules! log_info {
($($t:tt)*) => { ($($t:tt)*) => {
let s = std::ffi::CString::new(format!($($t)*)).unwrap(); let s = std::ffi::CString::new(format!($($t)*)).unwrap();