awooter: highly, highly WIP
This commit is contained in:
parent
6d9322457e
commit
d5d6a07c34
@ -29,6 +29,7 @@ option(EXTERNAL_CHIPDB "Create build with pre-built chipdb binaries" OFF)
|
|||||||
option(WERROR "pass -Werror to compiler (used for CI)" OFF)
|
option(WERROR "pass -Werror to compiler (used for CI)" OFF)
|
||||||
option(PROFILER "Link against libprofiler" OFF)
|
option(PROFILER "Link against libprofiler" OFF)
|
||||||
option(USE_IPO "Compile nextpnr with IPO" ON)
|
option(USE_IPO "Compile nextpnr with IPO" ON)
|
||||||
|
option(AWOOTER "Build awooter router" ON)
|
||||||
|
|
||||||
if (USE_IPO)
|
if (USE_IPO)
|
||||||
if (ipo_supported)
|
if (ipo_supported)
|
||||||
@ -99,6 +100,29 @@ if (EXTERNAL_CHIPDB)
|
|||||||
add_definitions("-DEXTERNAL_CHIPDB_ROOT=\"${EXTERNAL_CHIPDB_ROOT}\"")
|
add_definitions("-DEXTERNAL_CHIPDB_ROOT=\"${EXTERNAL_CHIPDB_ROOT}\"")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (AWOOTER)
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(Corrosion GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git GIT_TAG v0.3.0)
|
||||||
|
FetchContent_MakeAvailable(Corrosion)
|
||||||
|
corrosion_import_crate(MANIFEST_PATH common/route/awooter/rust/Cargo.toml)
|
||||||
|
|
||||||
|
# Enable cross-lang IPO if CXX is clang.
|
||||||
|
if (USE_IPO AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
# rustc and clang disagree on what the triple of Linux should be:
|
||||||
|
# rustc: x86_64-unknown-linux-gnu
|
||||||
|
# clang: x86_64-pc-linux-gnu
|
||||||
|
# ask clang to use the rustc triple instead.
|
||||||
|
set(CMAKE_C_COMPILER_TARGET x86_64-unknown-linux-gnu)
|
||||||
|
set(CMAKE_CXX_COMPILER_TARGET x86_64-unknown-linux-gnu)
|
||||||
|
|
||||||
|
# If we don't do this, IPO fails. I don't know why.
|
||||||
|
corrosion_set_cargo_flags(awooter "-Zbuild-std")
|
||||||
|
|
||||||
|
corrosion_add_target_rustflags(awooter "-Clinker-plugin-lto")
|
||||||
|
message(STATUS "Enabled cross-language IPO")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(PROGRAM_PREFIX "" CACHE STRING "Name prefix for executables")
|
set(PROGRAM_PREFIX "" CACHE STRING "Name prefix for executables")
|
||||||
|
|
||||||
# List of families to build
|
# List of families to build
|
||||||
@ -297,6 +321,11 @@ foreach (family ${ARCH})
|
|||||||
install(TARGETS ${PROGRAM_PREFIX}nextpnr-${family} RUNTIME DESTINATION bin)
|
install(TARGETS ${PROGRAM_PREFIX}nextpnr-${family} RUNTIME DESTINATION bin)
|
||||||
target_compile_definitions(${PROGRAM_PREFIX}nextpnr-${family} PRIVATE MAIN_EXECUTABLE)
|
target_compile_definitions(${PROGRAM_PREFIX}nextpnr-${family} PRIVATE MAIN_EXECUTABLE)
|
||||||
|
|
||||||
|
# Link in awooter, if enabled.
|
||||||
|
if (AWOOTER)
|
||||||
|
target_link_libraries(${PROGRAM_PREFIX}nextpnr-${family} PRIVATE awooter)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Add any new per-architecture targets here
|
# Add any new per-architecture targets here
|
||||||
if (BUILD_TESTS)
|
if (BUILD_TESTS)
|
||||||
if (COVERAGE)
|
if (COVERAGE)
|
||||||
|
16
Cargo.lock
generated
Normal file
16
Cargo.lock
generated
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "awooter"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.137"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
4
Cargo.toml
Normal file
4
Cargo.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"common/route/awooter/rust"
|
||||||
|
]
|
151
common/route/awooter.cc
Normal file
151
common/route/awooter.cc
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* nextpnr -- Next Generation Place and Route
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Lofty <lofty@yosyshq.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "nextpnr.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
USING_NEXTPNR_NAMESPACE;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
uint64_t wrap(T thing) {
|
||||||
|
static_assert(sizeof(T) <= 8, "T is too big for FFI");
|
||||||
|
uint64_t b = 0;
|
||||||
|
memcpy(&b, &thing, sizeof(T));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
BelId unwrap_bel(uint64_t bel) {
|
||||||
|
static_assert(sizeof(BelId) <= 8, "T is too big for FFI");
|
||||||
|
auto b = BelId();
|
||||||
|
memcpy(&b, &bel, sizeof(BelId));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
PipId unwrap_pip(uint64_t pip) {
|
||||||
|
static_assert(sizeof(PipId) <= 8, "T is too big for FFI");
|
||||||
|
auto p = PipId();
|
||||||
|
memcpy(&p, &pip, sizeof(PipId));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
WireId unwrap_wire(uint64_t wire) {
|
||||||
|
static_assert(sizeof(WireId) <= 8, "T is too big for FFI");
|
||||||
|
auto w = WireId();
|
||||||
|
memcpy(&w, &wire, sizeof(WireId));
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
USING_NEXTPNR_NAMESPACE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
DONE:
|
||||||
|
ctx->bindPip
|
||||||
|
ctx->bindWire
|
||||||
|
ctx->check
|
||||||
|
ctx->debug
|
||||||
|
ctx->estimateDelay
|
||||||
|
ctx->getDelayEpsilon
|
||||||
|
ctx->getPipDstWire
|
||||||
|
ctx->getPipSrcWire
|
||||||
|
ctx->getGridDimX
|
||||||
|
ctx->getGridDimY
|
||||||
|
ctx->id
|
||||||
|
ctx->nameOf
|
||||||
|
ctx->unbindWire
|
||||||
|
ctx->verbose
|
||||||
|
|
||||||
|
UNNECESSARY:
|
||||||
|
ctx->getDelayNS - all FFI calls go through it anyway.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
ctx->checkPipAvail
|
||||||
|
ctx->checkPipAvailForNet
|
||||||
|
ctx->checkWireAvail
|
||||||
|
ctx->getBelPinType
|
||||||
|
ctx->getBoundPipNet
|
||||||
|
ctx->getBoundWireNet
|
||||||
|
ctx->getNetinfoSinkWire
|
||||||
|
ctx->getNetinfoSinkWires
|
||||||
|
ctx->getNetinfoSourceWire
|
||||||
|
ctx->getPipDelay
|
||||||
|
ctx->getPipLocation
|
||||||
|
ctx->getPipsDownhill
|
||||||
|
ctx->getPipsUphill
|
||||||
|
ctx->getRouteBoundingBox
|
||||||
|
ctx->getWireBelPins
|
||||||
|
ctx->getWireDelay
|
||||||
|
ctx->getWires
|
||||||
|
ctx->getWireType
|
||||||
|
ctx->nameOfPip
|
||||||
|
ctx->nameOfWire
|
||||||
|
ctx->nets
|
||||||
|
ctx->nets.at
|
||||||
|
ctx->nets.size
|
||||||
|
ctx->rng64
|
||||||
|
ctx->setting<bool>
|
||||||
|
ctx->setting<float>
|
||||||
|
ctx->setting<int>
|
||||||
|
ctx->sorted_shuffle
|
||||||
|
*/
|
||||||
|
|
||||||
|
void npnr_log_info(const char *const format) { log_info("%s", format); }
|
||||||
|
void npnr_log_error(const char *const format) { log_error("%s", format); }
|
||||||
|
|
||||||
|
uint64_t npnr_belid_null() { return wrap(BelId()); }
|
||||||
|
|
||||||
|
int npnr_context_get_grid_dim_x(const Context *const ctx) { return ctx->getGridDimX(); }
|
||||||
|
int npnr_context_get_grid_dim_y(const Context *const ctx) { return ctx->getGridDimY(); }
|
||||||
|
void npnr_context_bind_bel(Context *ctx, uint64_t bel, CellInfo* cell, PlaceStrength strength) { return ctx->bindBel(unwrap_bel(bel), cell, strength); }
|
||||||
|
void npnr_context_unbind_bel(Context *ctx, uint64_t bel) { return ctx->unbindBel(unwrap_bel(bel)); }
|
||||||
|
bool npnr_context_check_bel_avail(Context *const ctx, uint64_t bel) { return ctx->checkBelAvail(unwrap_bel(bel)); }
|
||||||
|
void npnr_context_bind_wire(Context *ctx, uint64_t wire, NetInfo* net, PlaceStrength strength) { ctx->bindWire(unwrap_wire(wire), net, strength); }
|
||||||
|
void npnr_context_unbind_wire(Context *ctx, uint64_t wire) { ctx->unbindWire(unwrap_wire(wire)); }
|
||||||
|
void npnr_context_bind_pip(Context *ctx, uint64_t pip, NetInfo* net, PlaceStrength strength) { ctx->bindPip(unwrap_pip(pip), net, strength); }
|
||||||
|
void npnr_context_unbind_pip(Context *ctx, uint64_t pip) { ctx->unbindPip(unwrap_pip(pip)); }
|
||||||
|
uint64_t npnr_context_get_pip_src_wire(const Context *const ctx, uint64_t pip) { return wrap(ctx->getPipSrcWire(unwrap_pip(pip))); }
|
||||||
|
uint64_t npnr_context_get_pip_dst_wire(const Context *const ctx, uint64_t pip) { return wrap(ctx->getPipDstWire(unwrap_pip(pip))); }
|
||||||
|
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()); }
|
||||||
|
|
||||||
|
void npnr_context_check(const Context *const ctx) { ctx->check(); }
|
||||||
|
bool npnr_context_debug(const Context *const ctx) { return ctx->debug; }
|
||||||
|
IdString npnr_context_id(const Context *const ctx, const char *const str) { return ctx->id(str); }
|
||||||
|
const char *npnr_context_name_of(const Context *const ctx, IdString str) { return ctx->nameOf(str); }
|
||||||
|
bool npnr_context_verbose(const Context *const ctx) { return ctx->verbose; }
|
||||||
|
|
||||||
|
//NetInfo** npnr_context_nets(Context *ctx) { /* oh no */ }
|
||||||
|
|
||||||
|
extern bool npnr_router_awooter(Context *ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
bool router_awooter(Context *ctx) {
|
||||||
|
static_assert(std::is_standard_layout<IdString>::value == true, "IdString is not FFI-safe");
|
||||||
|
|
||||||
|
log_info("Running Awooter...\n");
|
||||||
|
auto result = npnr_router_awooter(ctx);
|
||||||
|
log_info("Router returned: %d\n", result);
|
||||||
|
NPNR_ASSERT_FALSE_STR("I haven't implemented anything beyond this yet.");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_END
|
30
common/route/awooter.h
Normal file
30
common/route/awooter.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* nextpnr -- Next Generation Place and Route
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Lofty <lofty@yosyshq.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AWOOTER_H
|
||||||
|
#define AWOOTER_H
|
||||||
|
|
||||||
|
#include "nextpnr.h"
|
||||||
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
extern bool router_awooter(Context* ctx);
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // AWOOTER_H
|
7
common/route/awooter/rust/Cargo.lock
generated
Normal file
7
common/route/awooter/rust/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust"
|
||||||
|
version = "0.1.0"
|
14
common/route/awooter/rust/Cargo.toml
Normal file
14
common/route/awooter/rust/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "awooter"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "awooter"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2"
|
31
common/route/awooter/rust/src/lib.rs
Normal file
31
common/route/awooter/rust/src/lib.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod npnr;
|
||||||
|
mod part;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn npnr_router_awooter(ctx: Option<NonNull<npnr::Context>>) -> bool {
|
||||||
|
std::panic::catch_unwind(move || {
|
||||||
|
let ctx: &mut npnr::Context = unsafe { ctx.expect("non-null context").as_mut() };
|
||||||
|
route(ctx)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|x| {
|
||||||
|
if let Ok(x) = x.downcast::<String>() {
|
||||||
|
log_error!("caught panic: {}", x);
|
||||||
|
}
|
||||||
|
false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn route(ctx: &mut npnr::Context) -> bool {
|
||||||
|
log_info!("Hello from Rust!\n");
|
||||||
|
log_info!(
|
||||||
|
"Running on a {}x{} grid\n",
|
||||||
|
ctx.grid_dim_x(),
|
||||||
|
ctx.grid_dim_y()
|
||||||
|
);
|
||||||
|
// let _belid = npnr::BelId::null();
|
||||||
|
log_info!("Managed to survive BelId()\n");
|
||||||
|
true
|
||||||
|
}
|
218
common/route/awooter/rust/src/npnr.rs
Normal file
218
common/route/awooter/rust/src/npnr.rs
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
use libc::c_char;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum PlaceStrength {
|
||||||
|
None = 0,
|
||||||
|
Weak = 1,
|
||||||
|
Strong = 2,
|
||||||
|
Placer = 3,
|
||||||
|
Fixed = 4,
|
||||||
|
Locked = 5,
|
||||||
|
User = 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CellInfo {
|
||||||
|
private: [u8; 0],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct NetInfo {
|
||||||
|
private: [u8; 0],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct IdString {
|
||||||
|
index: libc::c_int,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type representing a bel name.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct BelId {
|
||||||
|
_private: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BelId {
|
||||||
|
pub fn null() -> Self {
|
||||||
|
unsafe { npnr_belid_null() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct PipId {
|
||||||
|
_private: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PipId {
|
||||||
|
pub fn null() -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct WireId {
|
||||||
|
_private: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WireId {
|
||||||
|
pub fn null() -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Context {
|
||||||
|
_private: [u8; 0],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
/// Get grid X dimension. All bels and pips must have X coordinates in the range `0 .. getGridDimX()-1` (inclusive).
|
||||||
|
pub fn grid_dim_x(&self) -> i32 {
|
||||||
|
unsafe { npnr_context_get_grid_dim_x(self) as i32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get grid Y dimension. All bels and pips must have Y coordinates in the range `0 .. getGridDimY()-1` (inclusive).
|
||||||
|
pub fn grid_dim_y(&self) -> i32 {
|
||||||
|
unsafe { npnr_context_get_grid_dim_y(self) as i32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bind a given bel to a given cell with the given strength.
|
||||||
|
pub fn bind_bel(&mut self, bel: BelId, cell: &mut CellInfo, strength: PlaceStrength) {
|
||||||
|
unsafe { npnr_context_bind_bel(self, bel, cell, strength) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unbind a bel.
|
||||||
|
pub fn unbind_bel(&mut self, bel: BelId) {
|
||||||
|
unsafe { npnr_context_unbind_bel(self, bel) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the bel is available. A bel can be unavailable because it is bound, or because it is exclusive to some other resource that is bound.
|
||||||
|
pub fn check_bel_avail(&self, bel: BelId) -> bool {
|
||||||
|
unsafe { npnr_context_check_bel_avail(self, bel) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the cell the given bel is bound to, or nullptr if the bel is not bound.
|
||||||
|
pub fn bound_bel_cell(&self, bel: BelId) -> Option<&CellInfo> {
|
||||||
|
unsafe { npnr_context_get_bound_bel_cell(self, bel).as_ref() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bind a wire to a net. This method must be used when binding a wire that is driven by a bel pin. Use bindPip() when binding a wire that is driven by a pip.
|
||||||
|
pub fn bind_wire(&mut self, wire: WireId, net: &mut NetInfo, strength: PlaceStrength) {
|
||||||
|
unsafe { npnr_context_bind_wire(self, wire, net, strength) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unbind a wire. For wires that are driven by a pip, this will also unbind the driving pip.
|
||||||
|
pub fn unbind_wire(&mut self, wire: WireId) {
|
||||||
|
unsafe { npnr_context_unbind_wire(self, wire) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bid a pip to a net. This also bind the destination wire of that pip.
|
||||||
|
pub fn bind_pip(&mut self, pip: PipId, net: &mut NetInfo, strength: PlaceStrength) {
|
||||||
|
unsafe { npnr_context_bind_pip(self, pip, net, strength) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unbind a pip and the wire driven by that pip.
|
||||||
|
pub fn unbind_pip(&mut self, pip: PipId) {
|
||||||
|
unsafe { npnr_context_unbind_pip(self, pip) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the source wire for a pip.
|
||||||
|
pub fn pip_src_wire(&self, pip: PipId) -> WireId {
|
||||||
|
unsafe { npnr_context_get_pip_src_wire(self, pip) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the destination wire for a pip.
|
||||||
|
pub fn pip_dst_wire(&self, pip: PipId) -> WireId {
|
||||||
|
unsafe { npnr_context_get_pip_dst_wire(self, pip) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Should this be a Duration? Does that even make sense?
|
||||||
|
pub fn estimate_delay(&self, src: WireId, dst: WireId) -> f32 {
|
||||||
|
unsafe { npnr_context_estimate_delay(self, src, dst) as f32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check(&self) {
|
||||||
|
unsafe { npnr_context_check(self) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug(&self) -> bool {
|
||||||
|
unsafe { npnr_context_debug(self)}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(&self, s: &str) -> IdString {
|
||||||
|
let s = std::ffi::CString::new(s).unwrap();
|
||||||
|
unsafe { npnr_context_id(self, s.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name_of(&self, s: IdString) -> &CStr {
|
||||||
|
unsafe { CStr::from_ptr(npnr_context_name_of(self, s)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verbose(&self) -> bool {
|
||||||
|
unsafe { npnr_context_verbose(self) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn npnr_log_info(format: *const c_char);
|
||||||
|
pub fn npnr_log_error(format: *const c_char);
|
||||||
|
|
||||||
|
fn npnr_belid_null() -> BelId;
|
||||||
|
|
||||||
|
fn npnr_context_get_grid_dim_x(ctx: *const Context) -> libc::c_int;
|
||||||
|
fn npnr_context_get_grid_dim_y(ctx: *const Context) -> libc::c_int;
|
||||||
|
fn npnr_context_bind_bel(
|
||||||
|
ctx: *mut Context,
|
||||||
|
bel: BelId,
|
||||||
|
cell: *mut CellInfo,
|
||||||
|
strength: PlaceStrength,
|
||||||
|
);
|
||||||
|
fn npnr_context_unbind_bel(ctx: *mut Context, bel: BelId);
|
||||||
|
fn npnr_context_check_bel_avail(ctx: *const Context, bel: BelId) -> bool;
|
||||||
|
fn npnr_context_get_bound_bel_cell(ctx: *const Context, bel: BelId) -> *const CellInfo;
|
||||||
|
fn npnr_context_bind_wire(
|
||||||
|
ctx: *mut Context,
|
||||||
|
wire: WireId,
|
||||||
|
net: *mut NetInfo,
|
||||||
|
strength: PlaceStrength,
|
||||||
|
);
|
||||||
|
fn npnr_context_unbind_wire(ctx: *mut Context, wire: WireId);
|
||||||
|
fn npnr_context_bind_pip(
|
||||||
|
ctx: *mut Context,
|
||||||
|
pip: PipId,
|
||||||
|
net: *mut NetInfo,
|
||||||
|
strength: PlaceStrength,
|
||||||
|
);
|
||||||
|
fn npnr_context_unbind_pip(ctx: *mut Context, pip: PipId);
|
||||||
|
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_estimate_delay(ctx: *const Context, src: WireId, dst: WireId) -> libc::c_float;
|
||||||
|
|
||||||
|
fn npnr_context_check(ctx: *const Context);
|
||||||
|
fn npnr_context_debug(ctx: *const Context) -> bool;
|
||||||
|
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_verbose(ctx: *const Context) -> bool;
|
||||||
|
|
||||||
|
// fn npnr_context_nets(ctx: *const Context) -> *mut *mut NetInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! log_info {
|
||||||
|
($($t:tt)*) => {
|
||||||
|
let s = std::ffi::CString::new(format!($($t)*)).unwrap();
|
||||||
|
unsafe { crate::npnr::npnr_log_info(s.as_ptr()); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! log_error {
|
||||||
|
($($t:tt)*) => {
|
||||||
|
let s = std::ffi::CString::new(format!($($t)*)).unwrap();
|
||||||
|
unsafe { crate::npnr::npnr_log_error(s.as_ptr()); }
|
||||||
|
};
|
||||||
|
}
|
6
common/route/awooter/rust/src/part.rs
Normal file
6
common/route/awooter/rust/src/part.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use crate::npnr;
|
||||||
|
|
||||||
|
pub struct Partition {
|
||||||
|
parts: [Option<Box<Partition>>; 4],
|
||||||
|
borders: [[Vec<npnr::WireId>; 4]; 4]
|
||||||
|
}
|
@ -33,6 +33,7 @@
|
|||||||
#include "placer_static.h"
|
#include "placer_static.h"
|
||||||
#include "router1.h"
|
#include "router1.h"
|
||||||
#include "router2.h"
|
#include "router2.h"
|
||||||
|
#include "awooter.h"
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@ -696,6 +697,8 @@ bool Arch::route()
|
|||||||
} else if (router == "router2") {
|
} else if (router == "router2") {
|
||||||
router2(getCtx(), Router2Cfg(getCtx()));
|
router2(getCtx(), Router2Cfg(getCtx()));
|
||||||
result = true;
|
result = true;
|
||||||
|
} else if (router == "awooter") {
|
||||||
|
result = router_awooter(getCtx());
|
||||||
} else {
|
} else {
|
||||||
log_error("ECP5 architecture does not support router '%s'\n", router.c_str());
|
log_error("ECP5 architecture does not support router '%s'\n", router.c_str());
|
||||||
}
|
}
|
||||||
@ -1278,7 +1281,7 @@ const std::string Arch::defaultPlacer = "heap";
|
|||||||
const std::vector<std::string> Arch::availablePlacers = {"sa", "heap", "static"};
|
const std::vector<std::string> Arch::availablePlacers = {"sa", "heap", "static"};
|
||||||
|
|
||||||
const std::string Arch::defaultRouter = "router1";
|
const std::string Arch::defaultRouter = "router1";
|
||||||
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
const std::vector<std::string> Arch::availableRouters = {"router1", "router2", "awooter"};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
3
rust-toolchain.toml
Normal file
3
rust-toolchain.toml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "nightly-2022-08-06"
|
||||||
|
components = ["rust-src"]
|
Loading…
Reference in New Issue
Block a user