1
0
mirror of https://github.com/YosysHQ/nextpnr.git synced 2026-01-11 23:53:21 +00:00

rust: add getBels() binding (#1460)

This commit is contained in:
Lofty 2025-03-19 09:02:34 +00:00 committed by GitHub
parent c84879e4d5
commit 06992bda0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 185 additions and 70 deletions

2
3rdparty/corrosion vendored

@ -1 +1 @@
Subproject commit be76480232216a64f65e3b1d9794d68cbac6c690
Subproject commit b1fab721655c5c4b1b08a083d3cd29f163af75d0

View File

@ -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<Self::Item> {
@ -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<Self::Item> {
@ -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<Self::Item> {
@ -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<Self::Item> {
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<Self::Item> {
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<Self::Item> {
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();

View File

@ -55,24 +55,29 @@ static inline PipId unwrap_pip(const uint64_t pip) noexcept { return unwrap<PipI
static inline WireId unwrap_wire(const uint64_t wire) noexcept { return unwrap<WireId>(wire); }
} // namespace
template<typename T>
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<DownhillIter>;
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<UphillIter>;
struct UphillIterWrapper
{
UphillIter current;
UphillIter end;
using BelIter = decltype(Context(ArchArgs()).getBels().begin());
using BelIterWrapper = IterWrapper<BelIter>;
UphillIterWrapper(UphillIter begin, UphillIter end) : current(begin), end(end) {}
};
using PipIter = decltype(Context(ArchArgs()).getPips().begin());
using PipIterWrapper = IterWrapper<PipIter>;
using WireIter = decltype(Context(ArchArgs()).getWires().begin());
using WireIterWrapper = IterWrapper<WireIter>;
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);
}