Skip to content

Commit

Permalink
Add Nexus support.
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Jul 6, 2021
1 parent ed1cceb commit 2ecd51e
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/package.yml
Expand Up @@ -12,6 +12,11 @@ jobs:
submodules: recursive
- name: Set up Python
uses: actions/setup-python@v2
- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools setuptools_scm wheel
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Expand Up @@ -7,3 +7,6 @@
[submodule "prjtrellis-src"]
path = prjtrellis-src
url = https://github.com/YosysHQ/prjtrellis
[submodule "prjoxide-src"]
path = prjoxide-src
url = https://github.com/gatecat/prjoxide.git
14 changes: 12 additions & 2 deletions build.sh
Expand Up @@ -75,6 +75,15 @@ cmake -B libtrellis-build -S prjtrellis-src/libtrellis \
-DCMAKE_INSTALL_PREFIX=$(pwd)/libtrellis-prefix
make -C libtrellis-build install

cargo build --target-dir prjoxide-build \
--manifest-path prjoxide-src/libprjoxide/prjoxide/Cargo.toml \
--target wasm32-wasi \
--release

cargo install --target-dir prjoxide-build \
--path prjoxide-src/libprjoxide/prjoxide \
--root prjoxide-prefix

cmake -B nextpnr-bba-build -S nextpnr-src/bba
cmake --build nextpnr-bba-build

Expand All @@ -90,7 +99,8 @@ cmake -B nextpnr-build -S nextpnr-src \
-DBUILD_PYTHON=OFF \
-DEXTERNAL_CHIPDB=ON \
-DEXTERNAL_CHIPDB_ROOT=/share \
-DARCH="ice40;ecp5" \
-DARCH="ice40;ecp5;nexus" \
-DICESTORM_INSTALL_PREFIX=$(pwd)/icestorm-prefix \
-DTRELLIS_INSTALL_PREFIX=$(pwd)/libtrellis-prefix
-DTRELLIS_INSTALL_PREFIX=$(pwd)/libtrellis-prefix \
-DOXIDE_INSTALL_PREFIX=$(pwd)/prjoxide-prefix
cmake --build nextpnr-build
8 changes: 4 additions & 4 deletions package-pypi-ecp5.sh
Expand Up @@ -4,10 +4,10 @@ PYTHON=${PYTHON:-python}

mkdir -p pypi-ecp5/yowasp_nextpnr_ecp5/bin/
cp prjtrellis-build/ecppll.wasm \
prjtrellis-build/ecpbram.wasm \
prjtrellis-build/ecpmulti.wasm \
prjtrellis-build/ecppack.wasm \
prjtrellis-build/ecpunpack.wasm \
prjtrellis-build/ecpbram.wasm \
prjtrellis-build/ecpmulti.wasm \
prjtrellis-build/ecppack.wasm \
prjtrellis-build/ecpunpack.wasm \
nextpnr-build/nextpnr-ecp5.wasm \
pypi-ecp5/yowasp_nextpnr_ecp5/
mkdir -p pypi-ecp5/yowasp_nextpnr_ecp5/share/ecp5
Expand Down
15 changes: 15 additions & 0 deletions package-pypi-nexus.sh
@@ -0,0 +1,15 @@
#!/bin/sh -ex

PYTHON=${PYTHON:-python}

mkdir -p pypi-nexus/yowasp_nextpnr_nexus/bin/
cp prjoxide-build/wasm32-wasi/release/prjoxide.wasm \
nextpnr-build/nextpnr-nexus.wasm \
pypi-nexus/yowasp_nextpnr_nexus/
mkdir -p pypi-nexus/yowasp_nextpnr_nexus/share/nexus
cp nextpnr-build/nexus/chipdb/*.bin \
pypi-nexus/yowasp_nextpnr_nexus/share/nexus

cd pypi-nexus
rm -rf build && ${PYTHON} setup.py bdist_wheel
sha256sum dist/*.whl
1 change: 1 addition & 0 deletions prjoxide-src
Submodule prjoxide-src added at 67d385
7 changes: 7 additions & 0 deletions pypi-nexus/.gitignore
@@ -0,0 +1,7 @@
__pycache__/
/*.egg-info
/.eggs
/build
/dist

/yowasp_*/share
69 changes: 69 additions & 0 deletions pypi-nexus/setup.py
@@ -0,0 +1,69 @@
import os
from setuptools import setup, find_packages
from setuptools_scm.git import parse as parse_git


def version():
upstream_git = parse_git("../nextpnr-src")
if upstream_git.exact:
nextpnr_version = upstream_git.format_with("{tag}")
else:
nextpnr_version = upstream_git.format_with("{tag}.post{distance}")

package_git = parse_git("..")
if not package_git.dirty:
package_version = package_git.format_with(".dev{distance}")
else:
package_version = package_git.format_with(".dev{distance}+dirty")

return nextpnr_version + package_version


def long_description():
with open("../README.md") as f:
return f.read()


setup_info = dict(
name="yowasp-nextpnr-nexus",
version=version(),
install_requires=[
"importlib_resources; python_version<'3.9'",
"appdirs~=1.4",
"wasmtime>=0.20,<0.28"
],
packages=["yowasp_nextpnr_nexus"],
package_data={
"yowasp_nextpnr_nexus": [
"*.wasm",
"share/nexus/chipdb-*.bin",
],
},
entry_points={
"console_scripts": [
"yowasp-prjoxide = yowasp_nextpnr_nexus:_run_prjoxide_argv",
"yowasp-nextpnr-nexus = yowasp_nextpnr_nexus:_run_nextpnr_nexus_argv",
],
},
)


setup(
author="whitequark",
author_email="whitequark@whitequark.org",
description="nextpnr-nexus FPGA place and route tool",
long_description=long_description(),
long_description_content_type="text/markdown",
license="ISC", # same as Yosys
python_requires="~=3.5",
setup_requires=["setuptools_scm", "wheel"],
**setup_info,
project_urls={
"Homepage": "https://yowasp.github.io/",
"Source Code": "https://github.com/YoWASP/nextpnr",
"Bug Tracker": "https://github.com/YoWASP/nextpnr/issues",
},
classifiers=[
"License :: OSI Approved :: ISC License (ISCL)",
],
)
74 changes: 74 additions & 0 deletions pypi-nexus/yowasp_nextpnr_nexus/__init__.py
@@ -0,0 +1,74 @@
import os
import sys
import wasmtime
import pathlib
import hashlib
import appdirs
try:
from importlib import resources as importlib_resources
try:
importlib_resources.files # py3.9+ stdlib
except AttributeError:
import importlib_resources # py3.8- shim
except ImportError:
import importlib_resources # py3.6- shim


def _run_wasm_app(wasm_filename, argv):
module_binary = importlib_resources.read_binary(__package__, wasm_filename)
module_digest = hashlib.sha1(module_binary).digest()

wasi_cfg = wasmtime.WasiConfig()
wasi_cfg.argv = argv
wasi_cfg.preopen_dir(str(importlib_resources.files(__package__) / "share"), "/share")
wasi_cfg.preopen_dir("/", "/")
wasi_cfg.preopen_dir(".", ".")
wasi_cfg.inherit_stdin()
wasi_cfg.inherit_stdout()
wasi_cfg.inherit_stderr()

engine = wasmtime.Engine()
cache_path = pathlib.Path(os.getenv("YOWASP_CACHE_DIR", appdirs.user_cache_dir("yowasp")))
cache_path.mkdir(parents=True, exist_ok=True)
cache_filename = (cache_path / "{}-cache".format(wasm_filename))
digest_filename = (cache_path / "{}-digest".format(wasm_filename))
try:
with digest_filename.open("rb") as digest_file:
if digest_file.read() != module_digest:
raise Exception("cache miss")
with cache_filename.open("rb") as cache_file:
module = wasmtime.Module.deserialize(engine, cache_file.read())
except:
print("Preparing to run {}. This might take a while...".format(argv[0]), file=sys.stderr)
module = wasmtime.Module(engine, module_binary)
with cache_filename.open("wb") as cache_file:
cache_file.write(module.serialize())
with digest_filename.open("wb") as digest_file:
digest_file.write(module_digest)

store = wasmtime.Store(engine)
linker = wasmtime.Linker(store)
wasi = linker.define_wasi(wasmtime.WasiInstance(store,
"wasi_snapshot_preview1", wasi_cfg))
app = linker.instantiate(module)
try:
app.exports["_start"]()
return 0
except wasmtime.ExitTrap as trap:
return trap.code


def run_prjoxide(argv):
return _run_wasm_app("prjoxide.wasm", ["yowasp-prjoxide", *argv])


def _run_prjoxide_argv():
sys.exit(run_prjoxide(sys.argv[1:]))


def run_nextpnr_nexus(argv):
return _run_wasm_app("nextpnr-nexus.wasm", ["yowasp-nextpnr-nexus", *argv])


def _run_nextpnr_nexus_argv():
sys.exit(run_nextpnr_nexus(sys.argv[1:]))

0 comments on commit 2ecd51e

Please sign in to comment.