From 06992bda0abf55c13f40e1985ae87618d006fd54 Mon Sep 17 00:00:00 2001 From: Lofty Date: Wed, 19 Mar 2025 09:02:34 +0000 Subject: [PATCH] rust: add getBels() binding (#1460) --- 3rdparty/corrosion | 2 +- rust/nextpnr/src/lib.rs | 148 ++++++++++++++++++++++++++++++++++------ rust/rust.cc | 105 ++++++++++++++-------------- 3 files changed, 185 insertions(+), 70 deletions(-) diff --git a/3rdparty/corrosion b/3rdparty/corrosion index be764802..b1fab721 160000 --- a/3rdparty/corrosion +++ b/3rdparty/corrosion @@ -1 +1 @@ -Subproject commit be76480232216a64f65e3b1d9794d68cbac6c690 +Subproject commit b1fab721655c5c4b1b08a083d3cd29f163af75d0 diff --git a/rust/nextpnr/src/lib.rs b/rust/nextpnr/src/lib.rs index 66a96ee1..92427579 100644 --- a/rust/nextpnr/src/lib.rs +++ b/rust/nextpnr/src/lib.rs @@ -239,16 +239,19 @@ impl Context { v } - pub fn wires_leaking(&self) -> &[WireId] { - let mut wires = std::ptr::null_mut(); - let len = unsafe { npnr_context_get_wires_leak(self, &mut wires as *mut *mut WireId) }; - unsafe { std::slice::from_raw_parts(wires, len as usize) } + pub fn bels(&self) -> BelIter { + let iter = unsafe { npnr_context_get_bels(self) }; + BelIter { iter, phantom_data: PhantomData } } - pub fn pips_leaking(&self) -> &[PipId] { - let mut pips = std::ptr::null_mut(); - let len = unsafe { npnr_context_get_pips_leak(self, &mut pips as *mut *mut PipId) }; - unsafe { std::slice::from_raw_parts(pips, len as usize) } + pub fn pips(&self) -> PipIter { + let iter = unsafe { npnr_context_get_pips(self) }; + PipIter { iter, phantom_data: PhantomData } + } + + pub fn wires(&self) -> WireIter { + let iter = unsafe { npnr_context_get_wires(self) }; + WireIter { iter, phantom_data: PhantomData } } pub fn get_downhill_pips(&self, wire: WireId) -> DownhillPipsIter { @@ -377,8 +380,6 @@ extern "C" { fn npnr_context_delay_epsilon(ctx: &Context) -> f32; fn npnr_context_get_pip_delay(ctx: &Context, pip: PipId) -> f32; fn npnr_context_get_wire_delay(ctx: &Context, wire: WireId) -> f32; - fn npnr_context_get_wires_leak(ctx: &Context, wires: *mut *mut WireId) -> u64; - fn npnr_context_get_pips_leak(ctx: &Context, pips: *mut *mut PipId) -> u64; fn npnr_context_get_pip_location(ctx: &Context, pip: PipId) -> Loc; fn npnr_context_check_pip_avail_for_net( ctx: &Context, @@ -407,10 +408,6 @@ extern "C" { names: *mut *mut libc::c_int, nets: *mut *mut *mut NetInfo, ) -> u32; - fn npnr_context_get_pips_downhill(ctx: &Context, wire: WireId) -> &mut RawDownhillIter; - fn npnr_delete_downhill_iter(iter: &mut RawDownhillIter); - fn npnr_context_get_pips_uphill(ctx: &Context, wire: WireId) -> &mut RawUphillIter; - fn npnr_delete_uphill_iter(iter: &mut RawUphillIter); fn npnr_netinfo_driver(net: &mut NetInfo) -> Option<&mut PortRef>; fn npnr_netinfo_users_leak(net: &NetInfo, users: *mut *mut *const PortRef) -> u32; @@ -421,12 +418,35 @@ extern "C" { fn npnr_portref_cell(port: &PortRef) -> Option<&CellInfo>; fn npnr_cellinfo_get_location(info: &CellInfo) -> Loc; + fn npnr_context_get_pips_downhill(ctx: &Context, wire: WireId) -> &mut RawDownhillIter; + fn npnr_delete_downhill_iter(iter: &mut RawDownhillIter); fn npnr_inc_downhill_iter(iter: &mut RawDownhillIter); fn npnr_deref_downhill_iter(iter: &mut RawDownhillIter) -> PipId; fn npnr_is_downhill_iter_done(iter: &mut RawDownhillIter) -> bool; + + fn npnr_context_get_pips_uphill(ctx: &Context, wire: WireId) -> &mut RawUphillIter; + fn npnr_delete_uphill_iter(iter: &mut RawUphillIter); fn npnr_inc_uphill_iter(iter: &mut RawUphillIter); fn npnr_deref_uphill_iter(iter: &mut RawUphillIter) -> PipId; fn npnr_is_uphill_iter_done(iter: &mut RawUphillIter) -> bool; + + fn npnr_context_get_bels(ctx: &Context) -> &mut RawBelIter; + fn npnr_delete_bel_iter(iter: &mut RawBelIter); + fn npnr_inc_bel_iter(iter: &mut RawBelIter); + fn npnr_deref_bel_iter(iter: &mut RawBelIter) -> BelId; + fn npnr_is_bel_iter_done(iter: &mut RawBelIter) -> bool; + + fn npnr_context_get_pips(ctx: &Context) -> &mut RawPipIter; + fn npnr_delete_pip_iter(iter: &mut RawPipIter); + fn npnr_inc_pip_iter(iter: &mut RawPipIter); + fn npnr_deref_pip_iter(iter: &mut RawPipIter) -> PipId; + fn npnr_is_pip_iter_done(iter: &mut RawPipIter) -> bool; + + fn npnr_context_get_wires(ctx: &Context) -> &mut RawWireIter; + fn npnr_delete_wire_iter(iter: &mut RawWireIter); + fn npnr_inc_wire_iter(iter: &mut RawWireIter); + fn npnr_deref_wire_iter(iter: &mut RawWireIter) -> WireId; + fn npnr_is_wire_iter_done(iter: &mut RawWireIter) -> bool; } /// Store for the nets of a context. @@ -518,7 +538,7 @@ pub struct NetSinkWireIter<'a> { n: u32, } -impl<'a> Iterator for NetSinkWireIter<'a> { +impl Iterator for NetSinkWireIter<'_> { type Item = WireId; fn next(&mut self) -> Option { @@ -542,7 +562,7 @@ pub struct DownhillPipsIter<'a> { phantom_data: PhantomData<&'a PipId>, } -impl<'a> Iterator for DownhillPipsIter<'a> { +impl Iterator for DownhillPipsIter<'_> { type Item = PipId; fn next(&mut self) -> Option { @@ -556,7 +576,7 @@ impl<'a> Iterator for DownhillPipsIter<'a> { } } -impl<'a> Drop for DownhillPipsIter<'a> { +impl Drop for DownhillPipsIter<'_> { fn drop(&mut self) { unsafe { npnr_delete_downhill_iter(self.iter) }; } @@ -572,7 +592,7 @@ pub struct UphillPipsIter<'a> { phantom_data: PhantomData<&'a PipId>, } -impl<'a> Iterator for UphillPipsIter<'a> { +impl Iterator for UphillPipsIter<'_> { type Item = PipId; fn next(&mut self) -> Option { @@ -586,12 +606,102 @@ impl<'a> Iterator for UphillPipsIter<'a> { } } -impl<'a> Drop for UphillPipsIter<'a> { +impl Drop for UphillPipsIter<'_> { fn drop(&mut self) { unsafe { npnr_delete_uphill_iter(self.iter) }; } } +#[repr(C)] +struct RawBelIter { + content: [u8; 0], +} + +pub struct BelIter<'a> { + iter: &'a mut RawBelIter, + phantom_data: PhantomData<&'a BelId>, +} + +impl Iterator for BelIter<'_> { + type Item = BelId; + + fn next(&mut self) -> Option { + if unsafe { npnr_is_bel_iter_done(self.iter) } { + None + } else { + let pip = unsafe { npnr_deref_bel_iter(self.iter) }; + unsafe { npnr_inc_bel_iter(self.iter) }; + Some(pip) + } + } +} + +impl Drop for BelIter<'_> { + fn drop(&mut self) { + unsafe { npnr_delete_bel_iter(self.iter) }; + } +} + +#[repr(C)] +struct RawPipIter { + content: [u8; 0], +} + +pub struct PipIter<'a> { + iter: &'a mut RawPipIter, + phantom_data: PhantomData<&'a PipId>, +} + +impl Iterator for PipIter<'_> { + type Item = PipId; + + fn next(&mut self) -> Option { + if unsafe { npnr_is_pip_iter_done(self.iter) } { + None + } else { + let pip = unsafe { npnr_deref_pip_iter(self.iter) }; + unsafe { npnr_inc_pip_iter(self.iter) }; + Some(pip) + } + } +} + +impl Drop for PipIter<'_> { + fn drop(&mut self) { + unsafe { npnr_delete_pip_iter(self.iter) }; + } +} + +#[repr(C)] +struct RawWireIter { + content: [u8; 0], +} + +pub struct WireIter<'a> { + iter: &'a mut RawWireIter, + phantom_data: PhantomData<&'a WireId>, +} + +impl Iterator for WireIter<'_> { + type Item = WireId; + + fn next(&mut self) -> Option { + if unsafe { npnr_is_wire_iter_done(self.iter) } { + None + } else { + let pip = unsafe { npnr_deref_wire_iter(self.iter) }; + unsafe { npnr_inc_wire_iter(self.iter) }; + Some(pip) + } + } +} + +impl Drop for WireIter<'_> { + fn drop(&mut self) { + unsafe { npnr_delete_wire_iter(self.iter) }; + } +} + macro_rules! log_info { ($($t:tt)*) => { let s = std::ffi::CString::new(format!($($t)*)).unwrap(); diff --git a/rust/rust.cc b/rust/rust.cc index b59e1871..310cb66e 100644 --- a/rust/rust.cc +++ b/rust/rust.cc @@ -55,24 +55,29 @@ static inline PipId unwrap_pip(const uint64_t pip) noexcept { return unwrap(wire); } } // namespace +template +struct IterWrapper +{ + T current; + T end; + + IterWrapper(T begin, T end) : current(begin), end(end) {} +}; + using DownhillIter = decltype(Context(ArchArgs()).getPipsDownhill(WireId()).begin()); +using DownhillIterWrapper = IterWrapper; -struct DownhillIterWrapper -{ - DownhillIter current; - DownhillIter end; - - DownhillIterWrapper(DownhillIter begin, DownhillIter end) : current(begin), end(end) {} -}; using UphillIter = decltype(Context(ArchArgs()).getPipsUphill(WireId()).begin()); +using UphillIterWrapper = IterWrapper; -struct UphillIterWrapper -{ - UphillIter current; - UphillIter end; +using BelIter = decltype(Context(ArchArgs()).getBels().begin()); +using BelIterWrapper = IterWrapper; - UphillIterWrapper(UphillIter begin, UphillIter end) : current(begin), end(end) {} -}; +using PipIter = decltype(Context(ArchArgs()).getPips().begin()); +using PipIterWrapper = IterWrapper; + +using WireIter = decltype(Context(ArchArgs()).getWires().begin()); +using WireIterWrapper = IterWrapper; extern "C" { USING_NEXTPNR_NAMESPACE; @@ -129,36 +134,6 @@ bool npnr_context_check_pip_avail_for_net(const Context *ctx, uint64_t pip, NetI return ctx->checkPipAvailForNet(unwrap_pip(pip), net); } -uint64_t npnr_context_get_pips_leak(const Context *ctx, uint64_t **const pips) -{ - const auto ctx_pips{ctx->getPips()}; - const auto size{std::accumulate(ctx_pips.begin(), ctx_pips.end(), /*initial value*/ size_t{}, - [](size_t value, const auto & /*pip*/) { return value + 1U; })}; - *pips = new uint64_t[size]; - auto idx = 0; - for (const auto &pip : ctx_pips) { - (*pips)[idx] = wrap(pip); - idx++; - } - // Yes, by never deleting pip_vec, we leak memory. - return size; -} - -uint64_t npnr_context_get_wires_leak(const Context *ctx, uint64_t **const wires) -{ - const auto ctx_wires{ctx->getWires()}; - const auto size{std::accumulate(ctx_wires.begin(), ctx_wires.end(), /*initial value*/ size_t{}, - [](size_t value, const auto & /*wire*/) { return value + 1U; })}; - *wires = new uint64_t[size]; - auto idx = 0; - for (const auto &wire : ctx_wires) { - (*wires)[idx] = wrap(wire); - idx++; - } - // Yes, by never deleting wires, we leak memory. - return size; -} - void npnr_context_check(const Context *ctx) { ctx->check(); } bool npnr_context_debug(const Context *ctx) { return ctx->debug; } int npnr_context_id(const Context *ctx, const char *str) { return ctx->id(str).hash(); } @@ -198,6 +173,10 @@ DownhillIterWrapper *npnr_context_get_pips_downhill(Context *ctx, uint64_t wire_ return new DownhillIterWrapper(range.begin(), range.end()); } void npnr_delete_downhill_iter(DownhillIterWrapper *iter) { delete iter; } +void npnr_inc_downhill_iter(DownhillIterWrapper *iter) { ++iter->current; } +uint64_t npnr_deref_downhill_iter(DownhillIterWrapper *iter) { return wrap(*iter->current); } +bool npnr_is_downhill_iter_done(DownhillIterWrapper *iter) { return !(iter->current != iter->end); } + UphillIterWrapper *npnr_context_get_pips_uphill(Context *ctx, uint64_t wire_id) { auto wire = unwrap_wire(wire_id); @@ -205,6 +184,39 @@ UphillIterWrapper *npnr_context_get_pips_uphill(Context *ctx, uint64_t wire_id) return new UphillIterWrapper(range.begin(), range.end()); } void npnr_delete_uphill_iter(UphillIterWrapper *iter) { delete iter; } +void npnr_inc_uphill_iter(UphillIterWrapper *iter) { ++iter->current; } +uint64_t npnr_deref_uphill_iter(UphillIterWrapper *iter) { return wrap(*iter->current); } +bool npnr_is_uphill_iter_done(UphillIterWrapper *iter) { return !(iter->current != iter->end); } + +BelIterWrapper *npnr_context_get_bels(Context *ctx) +{ + auto range = ctx->getBels(); + return new BelIterWrapper(range.begin(), range.end()); +} +void npnr_delete_bel_iter(BelIterWrapper *iter) { delete iter; } +void npnr_inc_bel_iter(BelIterWrapper *iter) { ++iter->current; } +uint64_t npnr_deref_bel_iter(BelIterWrapper *iter) { return wrap(*iter->current); } +bool npnr_is_bel_iter_done(BelIterWrapper *iter) { return !(iter->current != iter->end); } + +PipIterWrapper *npnr_context_get_pips(Context *ctx) +{ + auto range = ctx->getPips(); + return new PipIterWrapper(range.begin(), range.end()); +} +void npnr_delete_pip_iter(PipIterWrapper *iter) { delete iter; } +void npnr_inc_pip_iter(PipIterWrapper *iter) { ++iter->current; } +uint64_t npnr_deref_pip_iter(PipIterWrapper *iter) { return wrap(*iter->current); } +bool npnr_is_pip_iter_done(PipIterWrapper *iter) { return !(iter->current != iter->end); } + +WireIterWrapper *npnr_context_get_wires(Context *ctx) +{ + auto range = ctx->getWires(); + return new WireIterWrapper(range.begin(), range.end()); +} +void npnr_delete_wire_iter(WireIterWrapper *iter) { delete iter; } +void npnr_inc_wire_iter(WireIterWrapper *iter) { ++iter->current; } +uint64_t npnr_deref_wire_iter(WireIterWrapper *iter) { return wrap(*iter->current); } +bool npnr_is_wire_iter_done(WireIterWrapper *iter) { return !(iter->current != iter->end); } PortRef *npnr_netinfo_driver(NetInfo *net) { @@ -239,13 +251,6 @@ void npnr_netinfo_udata_set(NetInfo *net, int32_t value) { net->udata = value; } CellInfo *npnr_portref_cell(const PortRef *port) { return port->cell; } Loc npnr_cellinfo_get_location(const CellInfo *info) { return info->getLocation(); } -void npnr_inc_downhill_iter(DownhillIterWrapper *iter) { ++iter->current; } -uint64_t npnr_deref_downhill_iter(DownhillIterWrapper *iter) { return wrap(*iter->current); } -bool npnr_is_downhill_iter_done(DownhillIterWrapper *iter) { return !(iter->current != iter->end); } -void npnr_inc_uphill_iter(UphillIterWrapper *iter) { ++iter->current; } -uint64_t npnr_deref_uphill_iter(UphillIterWrapper *iter) { return wrap(*iter->current); } -bool npnr_is_uphill_iter_done(UphillIterWrapper *iter) { return !(iter->current != iter->end); } - void rust_example_printnets(Context *ctx); }