diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index d5a4dad..97a7cb8 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -26,109 +26,119 @@ jobs: uses: actions/cache@v3 with: path: ~/.cache/ccache - key: ${{ runner.os }}- + key: nextpnr-${{ hashFiles('nextpnr-src', 'icestorm-src', 'prjtrellis-src', 'prjoxide-src', 'apycula-meta', 'build.sh') }} + restore-keys: | + nextpnr-${{ hashFiles('nextpnr-src', 'icestorm-src', 'prjtrellis-src', 'prjoxide-src', 'apycula-meta', 'build.sh') }} + nextpnr- - name: Set up ccache run: | ccache --max-size=2G -z - name: Build WASM binaries run: | ./build.sh - - name: Build iCE40 binary wheels + - name: Build Python artifacts run: | ./package-pypi-ice40.sh - - name: Upload iCE40 binary wheel artifact - uses: actions/upload-artifact@v3 - with: - name: wheel - path: pypi-ice40/dist/ - - name: Test iCE40 binary wheels - run: | - pip install pypi-ice40/dist/*.whl - yowasp-icepll -h || true - yowasp-icebram -h || true - yowasp-icemulti -h || true - yowasp-icepack -h || true - yowasp-iceunpack -h || true - yowasp-nextpnr-ice40 --help - yowasp-nextpnr-ice40 --hx8k --package ct256 --test - yowasp-nextpnr-ice40 --up5k --package sg48 --test - - name: Build ECP5 binary wheels - run: | ./package-pypi-ecp5.sh - - name: Upload ECP5 binary wheel artifact - uses: actions/upload-artifact@v3 - with: - name: wheel - path: pypi-ecp5/dist/ - - name: Test ECP5 binary wheels - run: | - pip install pypi-ecp5/dist/*.whl - yowasp-ecppll --help || true - yowasp-ecpbram --help - yowasp-ecpmulti --help || true - yowasp-ecppack --help || true - yowasp-ecpunpack --help || true - yowasp-nextpnr-ecp5 --help - yowasp-nextpnr-ecp5 --um5g-25k --package CABGA381 --test - - name: Build MachXO2 binary wheels - run: | ./package-pypi-machxo2.sh - - name: Upload MachXO2 binary wheel artifact - uses: actions/upload-artifact@v3 - with: - name: wheel - path: pypi-machxo2/dist/ - - name: Test MachXO2 binary wheels - run: | - pip install pypi-machxo2/dist/*.whl - yowasp-xo2pll --help || true - yowasp-xo2bram --help - yowasp-xo2multi --help || true - yowasp-xo2pack --help || true - yowasp-xo2unpack --help || true - yowasp-nextpnr-machxo2 --help - yowasp-nextpnr-machxo2 --device LCMXO2-1200HC-4SG32C --test - - name: Build Nexus binary wheels - run: | ./package-pypi-nexus.sh - - name: Upload Nexus binary wheel artifact + ./package-pypi-gowin.sh + - name: Upload Python artifact uses: actions/upload-artifact@v3 with: - name: wheel - path: pypi-nexus/dist/ - - name: Test Nexus binary wheels + name: dist-pypi + path: pypi-*/dist/ + - name: Build JavaScript artifacts run: | - pip install pypi-nexus/dist/*.whl - yowasp-prjoxide --help - yowasp-nextpnr-nexus --help - yowasp-nextpnr-nexus --device LIFCL-40-9BG400CES --test - - name: Build Gowin binary wheels - run: | - ./package-pypi-gowin.sh - - name: Upload Gowin binary wheel artifact + ./package-npmjs-ice40.sh + ./package-npmjs-ecp5.sh + ./package-npmjs-machxo2.sh + ./package-npmjs-nexus.sh + - name: Upload JavaScript artifact uses: actions/upload-artifact@v3 with: - name: wheel - path: pypi-gowin/dist/ - - name: Test Gowin binary wheels - run: | - pip install pypi-gowin/dist/*.whl - yowasp-nextpnr-gowin --help - yowasp-nextpnr-gowin --device GW1N-LV1QN48C6/I5 --test + name: dist-npmjs + path: npmjs-*/dist/ - name: Print ccache statistics run: | ccache -s - publish: + test-python: + needs: build + runs-on: ubuntu-latest + steps: + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Download Python artifacts + uses: actions/download-artifact@v3 + with: + name: dist-pypi + - name: Test iCE40 Python artifact + run: | + pip install pypi-ice40/dist/*.whl + yowasp-icepll -h || true + yowasp-icebram -h || true + yowasp-icemulti -h || true + yowasp-icepack -h || true + yowasp-iceunpack -h || true + yowasp-nextpnr-ice40 --help + yowasp-nextpnr-ice40 --hx8k --package ct256 --test + yowasp-nextpnr-ice40 --up5k --package sg48 --test + - name: Test ECP5 Python artifact + run: | + pip install pypi-ecp5/dist/*.whl + yowasp-ecppll --help || true + yowasp-ecpbram --help + yowasp-ecpmulti --help || true + yowasp-ecppack --help || true + yowasp-ecpunpack --help || true + yowasp-nextpnr-ecp5 --help + yowasp-nextpnr-ecp5 --um5g-25k --package CABGA381 --test + - name: Test MachXO2 Python artifact + run: | + pip install pypi-machxo2/dist/*.whl + yowasp-xo2pll --help || true + yowasp-xo2bram --help + yowasp-xo2multi --help || true + yowasp-xo2pack --help || true + yowasp-xo2unpack --help || true + yowasp-nextpnr-machxo2 --help + yowasp-nextpnr-machxo2 --device LCMXO2-1200HC-4SG32C --test + - name: Test Nexus Python artifact + run: | + pip install pypi-nexus/dist/*.whl + yowasp-prjoxide --help + yowasp-nextpnr-nexus --help + yowasp-nextpnr-nexus --device LIFCL-40-9BG400CES --test + - name: Test Gowin Python artifact + run: | + pip install pypi-gowin/dist/*.whl + yowasp-nextpnr-gowin --help + yowasp-nextpnr-gowin --device GW1N-LV1QN48C6/I5 --test + check: # group all `test (*)` workflows into one for the required status check + needs: [test-python] + if: always() && !contains(needs.*.result, 'cancelled') + runs-on: ubuntu-latest + steps: + - run: ${{ contains(needs.*.result, 'failure') && 'false' || 'true' }} + publish-python: needs: build runs-on: ubuntu-latest environment: publish permissions: id-token: write + if: "!contains(github.event.head_commit.message, 'skip py')" steps: - - uses: actions/download-artifact@v3 + - name: Download Python artifacts + uses: actions/download-artifact@v3 with: - name: wheel - path: dist/ + name: dist-pypi + path: dist-tree/ + - name: Prepare artifacts for publishing + run: | + mkdir dist + find dist-tree -name '*.whl' -exec mv {} dist/ \; - name: Publish wheels to Test PyPI if: "github.event_name == 'push' && startsWith(github.event.ref, 'refs/heads/develop')" uses: pypa/gh-action-pypi-publish@release/v1 @@ -137,6 +147,32 @@ jobs: - name: Publish wheels to PyPI if: "github.event_name == 'push' && startsWith(github.event.ref, 'refs/heads/release')" uses: pypa/gh-action-pypi-publish@release/v1 + publish-javascript: + needs: check + runs-on: ubuntu-latest + environment: publish + permissions: + id-token: write + if: "!contains(github.event.head_commit.message, 'skip js')" + steps: + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + registry-url: 'https://registry.npmjs.org' + - name: Download JavaScript artifacts + uses: actions/download-artifact@v3 + with: + name: dist-npmjs + path: dist/ + - name: Publish package to NPM (dry run) + if: "github.event_name == 'push' && startsWith(github.event.ref, 'refs/heads/develop')" + run: for pkg in $(find dist -name '*.tgz'); do npm publish --access public file:$pkg --dry-run; done + - name: Publish package to NPM + if: "github.event_name == 'push' && startsWith(github.event.ref, 'refs/heads/release')" + run: for pkg in $(find dist -name '*.tgz'); do npm publish --access public file:$pkg; done + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_CONFIG_PROVENANCE: true release: needs: build runs-on: ubuntu-latest diff --git a/build.sh b/build.sh index 9748221..088b7ba 100755 --- a/build.sh +++ b/build.sh @@ -4,8 +4,8 @@ export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) PYTHON=$(which ${PYTHON:-python}) -WASI_SDK=wasi-sdk-19.0 -WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz +WASI_SDK=wasi-sdk-20.0 +WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi WASI_SDK_PATH=$(pwd)/${WASI_SDK} @@ -17,7 +17,7 @@ EIGEN=eigen-3.4.0 EIGEN_URL=https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz if ! [ -d ${EIGEN} ]; then curl -L ${EIGEN_URL} | tar xzf -; fi -# Threading requires pre-release wasi-sdk +# Threading is currently experimental. WASI_TARGET="wasm32-wasi" WASI_SYSROOT="--sysroot ${WASI_SDK_PATH}/share/wasi-sysroot" WASI_CFLAGS="-flto" diff --git a/npmjs-common/.gitignore b/npmjs-common/.gitignore new file mode 100644 index 0000000..55e1e0c --- /dev/null +++ b/npmjs-common/.gitignore @@ -0,0 +1,9 @@ +/package-lock.json +/package.json +/node_modules +/dist + +/*.wasm +/gen +/share +/index.* \ No newline at end of file diff --git a/npmjs-common/package-in.json b/npmjs-common/package-in.json new file mode 100644 index 0000000..7771534 --- /dev/null +++ b/npmjs-common/package-in.json @@ -0,0 +1,41 @@ +{ + "name": "@yowasp/nextpnr-__ARCH__", + "version": "__VERSION__", + "description": "nextpnr-__ARCH__ FPGA place and route tool", + "author": "Catherine ", + "license": "ISC", + "homepage": "https://yowasp.org/", + "repository": { + "type": "git", + "url": "git+https://github.com/YoWASP/nextpnr.git" + }, + "bugs": { + "url": "https://github.com/YoWASP/nextpnr/issues" + }, + "type": "module", + "files": [ + "lib/api.d.ts", + "gen/bundle-*.js", + "gen/resources-*.js", + "gen/*.wasm", + "gen/share/" + ], + "exports": { + "node": "./gen/bundle-node.js", + "browser": "./gen/bundle-browser.js", + "types": "./lib/api.d.ts" + }, + "types": "./lib/api.d.ts", + "devDependencies": { + "@bytecodealliance/jco": "^0.14.1", + "@yowasp/runtime": "5.0.28", + "esbuild": "^0.19.8" + }, + "scripts": { + "pack": "yowasp-pack-resources gen/resources-nextpnr-__ARCH__.js gen share", + "transpile": "jco new __FILENAME__ --wasi-command --output __BASENAME__ && jco transpile __BASENAME__ --instantiation async --no-typescript --no-namespaced-exports --map 'wasi:io/*=runtime#io' --map 'wasi:cli/*=runtime#cli' --map 'wasi:clocks/*=runtime#*' --map 'wasi:filesystem/*=runtime#fs' --map 'wasi:random/*=runtime#random' --out-dir gen/", + "build:node": "esbuild --bundle lib/api.js --outfile=gen/bundle-node.js --format=esm --platform=node", + "build:browser": "esbuild --bundle lib/api.js --outfile=gen/bundle-browser.js --format=esm --platform=browser", + "all": "npm run transpile && npm run pack && npm run build:node && npm run build:browser" + } +} diff --git a/npmjs-common/prepare.py b/npmjs-common/prepare.py new file mode 100644 index 0000000..6f0f677 --- /dev/null +++ b/npmjs-common/prepare.py @@ -0,0 +1,48 @@ +import os +import re +import sys +import json +import subprocess + + +arch = sys.argv[1] + + +nextpnr_version_raw = subprocess.check_output([ + "git", "-C", "../nextpnr-src", "describe", "--tags", "HEAD" +], encoding="utf-8").strip() + +git_rev_list_raw = subprocess.check_output([ + "git", "rev-list", "HEAD" +], encoding="utf-8").split() + +nextpnr_version = re.match(r"^nextpnr-(\d+).(\d+)(?:-(\d+)-)?", nextpnr_version_raw) +nextpnr_major = int(nextpnr_version[1]) +nextpnr_minor = int(nextpnr_version[2]) +nextpnr_node = int(nextpnr_version[3] or "0") + +distance = len(git_rev_list_raw) - 1 + +if os.environ.get("RELEASE_BRANCH", "false") in ("true", "1", "yes"): + version = f"{nextpnr_major}.{nextpnr_minor}.{distance}" +else: + version = f"{nextpnr_major}.{nextpnr_minor + 1}.{nextpnr_node}-dev.{distance}" +print(f"version {version}") + + +with open("package-local.json", "rt") as f: + package_local = json.load(f) +with open("package-in.json", "rt") as f: + package_json = json.load(f) +package_json["version"] = version +package_json["name"] = package_json["name"].replace("__ARCH__", arch) +package_json["description"] = package_json["description"].replace("__ARCH__", arch) +package_json["scripts"]["pack"] = package_json["scripts"]["pack"].replace("__ARCH__", arch) +transpile_commands = [] +for transpile_file in package_local["scripts"]["transpile"]: + transpile_commands.append(package_json["scripts"]["transpile"] + .replace("__FILENAME__", transpile_file) + .replace("__BASENAME__", os.path.basename(transpile_file))) +package_json["scripts"]["transpile"] = " && ".join(transpile_commands) +with open("package.json", "wt") as f: + json.dump(package_json, f, indent=2) diff --git a/npmjs-ecp5/.gitignore b/npmjs-ecp5/.gitignore new file mode 100644 index 0000000..6e09722 --- /dev/null +++ b/npmjs-ecp5/.gitignore @@ -0,0 +1,9 @@ +/package-lock.json +/package.json +/node_modules +/dist + +/*.wasm +/gen +/share +/index.* diff --git a/npmjs-ecp5/lib/api.d.ts b/npmjs-ecp5/lib/api.d.ts new file mode 100644 index 0000000..15ee5ba --- /dev/null +++ b/npmjs-ecp5/lib/api.d.ts @@ -0,0 +1,30 @@ +export type Tree = { + [name: string]: Tree | string | Uint8Array +}; + +export class Exit extends Error { + code: number; + files: Tree; +} + +export type Command = (args?: string[], files?: Tree, options?: { + printLine?: (line: string) => void, + decodeASCII?: boolean +}) => Promise; + + +export const runEcppll: Command; +export const runEcpbram: Command; +export const runEcpmulti: Command; +export const runEcppack: Command; +export const runEcpunpack: Command; +export const runNextpnrEcp5: Command; + +export const commands: { + 'ecppll': Command, + 'ecpbram': Command, + 'ecpmulti': Command, + 'ecppack': Command, + 'ecpunpack': Command, + 'nextpnr-ecp5': Command, +}; diff --git a/npmjs-ecp5/lib/api.js b/npmjs-ecp5/lib/api.js new file mode 100644 index 0000000..b0dd2a8 --- /dev/null +++ b/npmjs-ecp5/lib/api.js @@ -0,0 +1,47 @@ +import { Application } from '@yowasp/runtime'; +import { instantiate as instantiateEcppll } from '../gen/ecppll.js'; +import { instantiate as instantiateEcpbram } from '../gen/ecpbram.js'; +import { instantiate as instantiateEcpmulti } from '../gen/ecpmulti.js'; +import { instantiate as instantiateEcppack } from '../gen/ecppack.js'; +import { instantiate as instantiateEcpunpack } from '../gen/ecpunpack.js'; +import { instantiate as instantiateNextpnrEcp5 } from '../gen/nextpnr-ecp5.js'; + +export { Exit } from '@yowasp/runtime'; + +const resourceFileURL = new URL('./resources-nextpnr-ecp5.js', import.meta.url); + +const ecppll = new Application(resourceFileURL, instantiateEcppll, 'yowasp-ecppll'); +const runEcppll = ecppll.run.bind(ecppll); + +const ecpbram = new Application(resourceFileURL, instantiateEcpbram, 'yowasp-ecpbram'); +const runEcpbram = ecpbram.run.bind(ecpbram); + +const ecpmulti = new Application(resourceFileURL, instantiateEcpmulti, 'yowasp-ecpmulti'); +const runEcpmulti = ecpmulti.run.bind(ecpmulti); + +const ecppack = new Application(resourceFileURL, instantiateEcppack, 'yowasp-ecppack'); +const runEcppack = ecppack.run.bind(ecppack); + +const ecpunpack = new Application(resourceFileURL, instantiateEcpunpack, 'yowasp-ecpunpack'); +const runEcpunpack = ecpunpack.run.bind(ecpunpack); + +const nextpnrEcp5 = new Application(resourceFileURL, instantiateNextpnrEcp5, 'yowasp-nextpnr-ecp5'); +const runNextpnrEcp5 = nextpnrEcp5.run.bind(nextpnrEcp5); + +export { + runEcppll, + runEcpbram, + runEcpmulti, + runEcppack, + runEcpunpack, + runNextpnrEcp5, +}; + +export const commands = { + 'ecppll': runEcppll, + 'ecpbram': runEcpbram, + 'ecpmulti': runEcpmulti, + 'ecppack': runEcppack, + 'ecpunpack': runEcpunpack, + 'nextpnr-ecp5': runNextpnrEcp5, +}; diff --git a/npmjs-ecp5/package-in.json b/npmjs-ecp5/package-in.json new file mode 120000 index 0000000..da46002 --- /dev/null +++ b/npmjs-ecp5/package-in.json @@ -0,0 +1 @@ +../npmjs-common/package-in.json \ No newline at end of file diff --git a/npmjs-ecp5/package-local.json b/npmjs-ecp5/package-local.json new file mode 100644 index 0000000..b6ae313 --- /dev/null +++ b/npmjs-ecp5/package-local.json @@ -0,0 +1,12 @@ +{ + "scripts": { + "transpile": [ + "../prjtrellis-build/ecppll.wasm", + "../prjtrellis-build/ecpbram.wasm", + "../prjtrellis-build/ecpmulti.wasm", + "../prjtrellis-build/ecppack.wasm", + "../prjtrellis-build/ecpunpack.wasm", + "../nextpnr-build/nextpnr-ecp5.wasm" + ] + } +} \ No newline at end of file diff --git a/npmjs-ecp5/prepare.py b/npmjs-ecp5/prepare.py new file mode 120000 index 0000000..4fd5d71 --- /dev/null +++ b/npmjs-ecp5/prepare.py @@ -0,0 +1 @@ +../npmjs-common/prepare.py \ No newline at end of file diff --git a/npmjs-ice40/.gitignore b/npmjs-ice40/.gitignore new file mode 100644 index 0000000..6e09722 --- /dev/null +++ b/npmjs-ice40/.gitignore @@ -0,0 +1,9 @@ +/package-lock.json +/package.json +/node_modules +/dist + +/*.wasm +/gen +/share +/index.* diff --git a/npmjs-ice40/lib/api.d.ts b/npmjs-ice40/lib/api.d.ts new file mode 100644 index 0000000..90d318d --- /dev/null +++ b/npmjs-ice40/lib/api.d.ts @@ -0,0 +1,30 @@ +export type Tree = { + [name: string]: Tree | string | Uint8Array +}; + +export class Exit extends Error { + code: number; + files: Tree; +} + +export type Command = (args?: string[], files?: Tree, options?: { + printLine?: (line: string) => void, + decodeASCII?: boolean +}) => Promise; + + +export const runIcepll: Command; +export const runIcebram: Command; +export const runIcemulti: Command; +export const runIcepack: Command; +export const runIceunpack: Command; +export const runNextpnrIce40: Command; + +export const commands: { + 'icepll': Command, + 'icebram': Command, + 'icemulti': Command, + 'icepack': Command, + 'iceunpack': Command, + 'nextpnr-ice40': Command, +}; diff --git a/npmjs-ice40/lib/api.js b/npmjs-ice40/lib/api.js new file mode 100644 index 0000000..bdf64b3 --- /dev/null +++ b/npmjs-ice40/lib/api.js @@ -0,0 +1,46 @@ +import { Application } from '@yowasp/runtime'; +import { instantiate as instantiateIcepll } from '../gen/icepll.js'; +import { instantiate as instantiateIcebram } from '../gen/icebram.js'; +import { instantiate as instantiateIcemulti } from '../gen/icemulti.js'; +import { instantiate as instantiateIcepack } from '../gen/icepack.js'; +import { instantiate as instantiateNextpnrIce40 } from '../gen/nextpnr-ice40.js'; + +export { Exit } from '@yowasp/runtime'; + +const resourceFileURL = new URL('./resources-nextpnr-ice40.js', import.meta.url); + +const icepll = new Application(resourceFileURL, instantiateIcepll, 'yowasp-icepll'); +const runIcepll = icepll.run.bind(icepll); + +const icebram = new Application(resourceFileURL, instantiateIcebram, 'yowasp-icebram'); +const runIcebram = icebram.run.bind(icebram); + +const icemulti = new Application(resourceFileURL, instantiateIcemulti, 'yowasp-icemulti'); +const runIcemulti = icemulti.run.bind(icemulti); + +const icepack = new Application(resourceFileURL, instantiateIcepack, 'yowasp-icepack'); +const runIcepack = icepack.run.bind(icepack); + +const iceunpack = new Application(resourceFileURL, instantiateIcepack, 'yowasp-iceunpack'); +const runIceunpack = iceunpack.run.bind(iceunpack); + +const nextpnrIce40 = new Application(resourceFileURL, instantiateNextpnrIce40, 'yowasp-nextpnr-ice40'); +const runNextpnrIce40 = nextpnrIce40.run.bind(nextpnrIce40); + +export { + runIcepll, + runIcebram, + runIcemulti, + runIcepack, + runIceunpack, + runNextpnrIce40, +}; + +export const commands = { + 'icepll': runIcepll, + 'icebram': runIcebram, + 'icemulti': runIcemulti, + 'icepack': runIcepack, + 'iceunpack': runIceunpack, + 'nextpnr-ice40': runNextpnrIce40, +}; diff --git a/npmjs-ice40/package-in.json b/npmjs-ice40/package-in.json new file mode 120000 index 0000000..da46002 --- /dev/null +++ b/npmjs-ice40/package-in.json @@ -0,0 +1 @@ +../npmjs-common/package-in.json \ No newline at end of file diff --git a/npmjs-ice40/package-local.json b/npmjs-ice40/package-local.json new file mode 100644 index 0000000..b080982 --- /dev/null +++ b/npmjs-ice40/package-local.json @@ -0,0 +1,11 @@ +{ + "scripts": { + "transpile": [ + "../icestorm-prefix/bin/icepll.wasm", + "../icestorm-prefix/bin/icebram.wasm", + "../icestorm-prefix/bin/icemulti.wasm", + "../icestorm-prefix/bin/icepack.wasm", + "../nextpnr-build/nextpnr-ice40.wasm" + ] + } +} \ No newline at end of file diff --git a/npmjs-ice40/prepare.py b/npmjs-ice40/prepare.py new file mode 120000 index 0000000..4fd5d71 --- /dev/null +++ b/npmjs-ice40/prepare.py @@ -0,0 +1 @@ +../npmjs-common/prepare.py \ No newline at end of file diff --git a/npmjs-machxo2/.gitignore b/npmjs-machxo2/.gitignore new file mode 100644 index 0000000..c047e5a --- /dev/null +++ b/npmjs-machxo2/.gitignore @@ -0,0 +1,8 @@ +/package-lock.json +/package.json +/node_modules +/dist + +/*.wasm +/gen +/share diff --git a/npmjs-machxo2/lib/api.d.ts b/npmjs-machxo2/lib/api.d.ts new file mode 100644 index 0000000..99414f3 --- /dev/null +++ b/npmjs-machxo2/lib/api.d.ts @@ -0,0 +1,30 @@ +export type Tree = { + [name: string]: Tree | string | Uint8Array +}; + +export class Exit extends Error { + code: number; + files: Tree; +} + +export type Command = (args?: string[], files?: Tree, options?: { + printLine?: (line: string) => void, + decodeASCII?: boolean +}) => Promise; + + +export const runEcppll: Command; +export const runEcpbram: Command; +export const runEcpmulti: Command; +export const runEcppack: Command; +export const runEcpunpack: Command; +export const runNextpnrMachxo2: Command; + +export const commands: { + 'ecppll': Command, + 'ecpbram': Command, + 'ecpmulti': Command, + 'ecppack': Command, + 'ecpunpack': Command, + 'nextpnr-machxo2': Command, +}; diff --git a/npmjs-machxo2/lib/api.js b/npmjs-machxo2/lib/api.js new file mode 100644 index 0000000..db9f11b --- /dev/null +++ b/npmjs-machxo2/lib/api.js @@ -0,0 +1,47 @@ +import { Application } from '@yowasp/runtime'; +import { instantiate as instantiateEcppll } from '../gen/ecppll.js'; +import { instantiate as instantiateEcpbram } from '../gen/ecpbram.js'; +import { instantiate as instantiateEcpmulti } from '../gen/ecpmulti.js'; +import { instantiate as instantiateEcppack } from '../gen/ecppack.js'; +import { instantiate as instantiateEcpunpack } from '../gen/ecpunpack.js'; +import { instantiate as instantiateNextpnrMachxo2 } from '../gen/nextpnr-machxo2.js'; + +export { Exit } from '@yowasp/runtime'; + +const resourceFileURL = new URL('./resources-nextpnr-machxo2.js', import.meta.url); + +const ecppll = new Application(resourceFileURL, instantiateEcppll, 'yowasp-ecppll'); +const runEcppll = ecppll.run.bind(ecppll); + +const ecpbram = new Application(resourceFileURL, instantiateEcpbram, 'yowasp-ecpbram'); +const runEcpbram = ecpbram.run.bind(ecpbram); + +const ecpmulti = new Application(resourceFileURL, instantiateEcpmulti, 'yowasp-ecpmulti'); +const runEcpmulti = ecpmulti.run.bind(ecpmulti); + +const ecppack = new Application(resourceFileURL, instantiateEcppack, 'yowasp-ecppack'); +const runEcppack = ecppack.run.bind(ecppack); + +const ecpunpack = new Application(resourceFileURL, instantiateEcpunpack, 'yowasp-ecpunpack'); +const runEcpunpack = ecpunpack.run.bind(ecpunpack); + +const nextpnrMachxo2 = new Application(resourceFileURL, instantiateNextpnrMachxo2, 'yowasp-nextpnr-machxo2'); +const runNextpnrMachxo2 = nextpnrMachxo2.run.bind(nextpnrMachxo2); + +export { + runEcppll, + runEcpbram, + runEcpmulti, + runEcppack, + runEcpunpack, + runNextpnrMachxo2, +}; + +export const commands = { + 'ecppll': runEcppll, + 'ecpbram': runEcpbram, + 'ecpmulti': runEcpmulti, + 'ecppack': runEcppack, + 'ecpunpack': runEcpunpack, + 'nextpnr-machxo2': runNextpnrMachxo2, +}; diff --git a/npmjs-machxo2/package-in.json b/npmjs-machxo2/package-in.json new file mode 120000 index 0000000..da46002 --- /dev/null +++ b/npmjs-machxo2/package-in.json @@ -0,0 +1 @@ +../npmjs-common/package-in.json \ No newline at end of file diff --git a/npmjs-machxo2/package-local.json b/npmjs-machxo2/package-local.json new file mode 100644 index 0000000..d092296 --- /dev/null +++ b/npmjs-machxo2/package-local.json @@ -0,0 +1,12 @@ +{ + "scripts": { + "transpile": [ + "../prjtrellis-build/ecppll.wasm", + "../prjtrellis-build/ecpbram.wasm", + "../prjtrellis-build/ecpmulti.wasm", + "../prjtrellis-build/ecppack.wasm", + "../prjtrellis-build/ecpunpack.wasm", + "../nextpnr-build/nextpnr-machxo2.wasm" + ] + } +} \ No newline at end of file diff --git a/npmjs-machxo2/prepare.py b/npmjs-machxo2/prepare.py new file mode 120000 index 0000000..4fd5d71 --- /dev/null +++ b/npmjs-machxo2/prepare.py @@ -0,0 +1 @@ +../npmjs-common/prepare.py \ No newline at end of file diff --git a/npmjs-nexus/.gitignore b/npmjs-nexus/.gitignore new file mode 100644 index 0000000..55e1e0c --- /dev/null +++ b/npmjs-nexus/.gitignore @@ -0,0 +1,9 @@ +/package-lock.json +/package.json +/node_modules +/dist + +/*.wasm +/gen +/share +/index.* \ No newline at end of file diff --git a/npmjs-nexus/lib/api.d.ts b/npmjs-nexus/lib/api.d.ts new file mode 100644 index 0000000..f61489a --- /dev/null +++ b/npmjs-nexus/lib/api.d.ts @@ -0,0 +1,22 @@ +export type Tree = { + [name: string]: Tree | string | Uint8Array +}; + +export class Exit extends Error { + code: number; + files: Tree; +} + +export type Command = (args?: string[], files?: Tree, options?: { + printLine?: (line: string) => void, + decodeASCII?: boolean +}) => Promise; + + +export const runPrjoxide: Command; +export const runNextpnrNexus: Command; + +export const commands: { + 'prjoxide': Command, + 'nextpnr-nexus': Command, +}; diff --git a/npmjs-nexus/lib/api.js b/npmjs-nexus/lib/api.js new file mode 100644 index 0000000..698a848 --- /dev/null +++ b/npmjs-nexus/lib/api.js @@ -0,0 +1,23 @@ +import { Application } from '@yowasp/runtime'; +import { instantiate as instantiatePrjoxide } from '../gen/prjoxide.js'; +import { instantiate as instantiateNextpnrNexus } from '../gen/nextpnr-nexus.js'; + +export { Exit } from '@yowasp/runtime'; + +const resourceFileURL = new URL('./resources-nextpnr-nexus.js', import.meta.url); + +const prjoxide = new Application(resourceFileURL, instantiatePrjoxide, 'yowasp-prjoxide'); +const runPrjoxide = prjoxide.run.bind(prjoxide); + +const nextpnrNexus = new Application(resourceFileURL, instantiateNextpnrNexus, 'yowasp-nextpnr-nexus'); +const runNextpnrNexus = nextpnrNexus.run.bind(nextpnrNexus); + +export { + runPrjoxide, + runNextpnrNexus, +}; + +export const commands = { + 'prjoxide': runPrjoxide, + 'nextpnr-nexus': runNextpnrNexus, +}; diff --git a/npmjs-nexus/package-in.json b/npmjs-nexus/package-in.json new file mode 120000 index 0000000..da46002 --- /dev/null +++ b/npmjs-nexus/package-in.json @@ -0,0 +1 @@ +../npmjs-common/package-in.json \ No newline at end of file diff --git a/npmjs-nexus/package-local.json b/npmjs-nexus/package-local.json new file mode 100644 index 0000000..6dd30f8 --- /dev/null +++ b/npmjs-nexus/package-local.json @@ -0,0 +1,8 @@ +{ + "scripts": { + "transpile": [ + "../prjoxide-build/wasm32-wasi/release/prjoxide.wasm", + "../nextpnr-build/nextpnr-nexus.wasm" + ] + } +} \ No newline at end of file diff --git a/npmjs-nexus/prepare.py b/npmjs-nexus/prepare.py new file mode 120000 index 0000000..4fd5d71 --- /dev/null +++ b/npmjs-nexus/prepare.py @@ -0,0 +1 @@ +../npmjs-common/prepare.py \ No newline at end of file diff --git a/package-npmjs-ecp5.sh b/package-npmjs-ecp5.sh new file mode 100755 index 0000000..e7c33ba --- /dev/null +++ b/package-npmjs-ecp5.sh @@ -0,0 +1,21 @@ +#!/bin/sh -ex + +cd $(dirname $0) + +PYTHON=${PYTHON:-python} + +mkdir -p npmjs-ecp5/share/ecp5 +cp nextpnr-build/ecp5/chipdb/*.bin \ + npmjs-ecp5/share/ecp5 +mkdir -p npmjs-ecp5/share/trellis/database +cp -r prjtrellis-src/database/ECP5 \ + prjtrellis-src/database/devices.json \ + npmjs-ecp5/share/trellis/database + +cd npmjs-ecp5 +${PYTHON} prepare.py ecp5 +npm install +npm run all + +mkdir -p dist +npm pack --pack-destination dist diff --git a/package-npmjs-ice40.sh b/package-npmjs-ice40.sh new file mode 100755 index 0000000..be8d613 --- /dev/null +++ b/package-npmjs-ice40.sh @@ -0,0 +1,17 @@ +#!/bin/sh -ex + +cd $(dirname $0) + +PYTHON=${PYTHON:-python} + +mkdir -p npmjs-ice40/share/ice40 +cp nextpnr-build/ice40/chipdb/*.bin \ + npmjs-ice40/share/ice40 + +cd npmjs-ice40 +${PYTHON} prepare.py ice40 +npm install +npm run all + +mkdir -p dist +npm pack --pack-destination dist diff --git a/package-npmjs-machxo2.sh b/package-npmjs-machxo2.sh new file mode 100755 index 0000000..558295d --- /dev/null +++ b/package-npmjs-machxo2.sh @@ -0,0 +1,21 @@ +#!/bin/sh -ex + +cd $(dirname $0) + +PYTHON=${PYTHON:-python} + +mkdir -p npmjs-machxo2/share/machxo2 +cp nextpnr-build/machxo2/chipdb/*.bin \ + npmjs-machxo2/share/machxo2 +mkdir -p npmjs-machxo2/share/trellis/database +cp -r prjtrellis-src/database/MachXO* \ + prjtrellis-src/database/devices.json \ + npmjs-machxo2/share/trellis/database + +cd npmjs-machxo2 +${PYTHON} prepare.py machxo2 +npm install +npm run all + +mkdir -p dist +npm pack --pack-destination dist diff --git a/package-npmjs-nexus.sh b/package-npmjs-nexus.sh new file mode 100755 index 0000000..f3ef483 --- /dev/null +++ b/package-npmjs-nexus.sh @@ -0,0 +1,17 @@ +#!/bin/sh -ex + +cd $(dirname $0) + +PYTHON=${PYTHON:-python} + +mkdir -p npmjs-nexus/share/nexus +cp nextpnr-build/nexus/chipdb/*.bin \ + npmjs-nexus/share/nexus + +cd npmjs-nexus +${PYTHON} prepare.py nexus +npm install +npm run all + +mkdir -p dist +npm pack --pack-destination dist diff --git a/package-pypi-ecp5.sh b/package-pypi-ecp5.sh index 4da0d82..121065d 100755 --- a/package-pypi-ecp5.sh +++ b/package-pypi-ecp5.sh @@ -2,6 +2,8 @@ PYTHON=${PYTHON:-python} +cd $(dirname $0) + mkdir -p pypi-ecp5/yowasp_nextpnr_ecp5/bin/ cp prjtrellis-build/ecppll.wasm \ prjtrellis-build/ecpbram.wasm \ diff --git a/package-pypi-gowin.sh b/package-pypi-gowin.sh index 12eac83..07a526b 100755 --- a/package-pypi-gowin.sh +++ b/package-pypi-gowin.sh @@ -2,6 +2,8 @@ PYTHON=${PYTHON:-python} +cd $(dirname $0) + mkdir -p pypi-gowin/yowasp_nextpnr_gowin/bin/ cp nextpnr-build/nextpnr-gowin.wasm \ pypi-gowin/yowasp_nextpnr_gowin/ diff --git a/package-pypi-ice40.sh b/package-pypi-ice40.sh index 67233b3..52802d2 100755 --- a/package-pypi-ice40.sh +++ b/package-pypi-ice40.sh @@ -2,6 +2,8 @@ PYTHON=${PYTHON:-python} +cd $(dirname $0) + mkdir -p pypi-ice40/yowasp_nextpnr_ice40/bin/ cp icestorm-prefix/bin/icepll.wasm \ icestorm-prefix/bin/icebram.wasm \ diff --git a/package-pypi-machxo2.sh b/package-pypi-machxo2.sh index 2414526..0a6c2a0 100755 --- a/package-pypi-machxo2.sh +++ b/package-pypi-machxo2.sh @@ -2,6 +2,8 @@ PYTHON=${PYTHON:-python} +cd $(dirname $0) + mkdir -p pypi-machxo2/yowasp_nextpnr_machxo2/bin/ cp prjtrellis-build/ecppll.wasm \ prjtrellis-build/ecpbram.wasm \ @@ -14,7 +16,7 @@ mkdir -p pypi-machxo2/yowasp_nextpnr_machxo2/share/machxo2 cp nextpnr-build/machxo2/chipdb/*.bin \ pypi-machxo2/yowasp_nextpnr_machxo2/share/machxo2 mkdir -p pypi-machxo2/yowasp_nextpnr_machxo2/share/trellis/database -cp -r prjtrellis-src/database/ECP5 \ +cp -r prjtrellis-src/database/MachXO* \ prjtrellis-src/database/devices.json \ pypi-machxo2/yowasp_nextpnr_machxo2/share/trellis/database diff --git a/package-pypi-nexus.sh b/package-pypi-nexus.sh index 2d9aa1d..1532cb4 100755 --- a/package-pypi-nexus.sh +++ b/package-pypi-nexus.sh @@ -2,6 +2,8 @@ PYTHON=${PYTHON:-python} +cd $(dirname $0) + mkdir -p pypi-nexus/yowasp_nextpnr_nexus/bin/ cp prjoxide-build/wasm32-wasi/release/prjoxide.wasm \ nextpnr-build/nextpnr-nexus.wasm \