Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# Optional CIRCT runtime overrides.
# Optional MOX runtime overrides.
# Tool artifacts:
VITE_CIRCT_VERILOG_JS_URL=/circt/circt-verilog.js
VITE_CIRCT_VERILOG_WASM_URL=/circt/circt-verilog.wasm
VITE_CIRCT_SIM_JS_URL=/circt/circt-sim.js
VITE_CIRCT_SIM_WASM_URL=/circt/circt-sim.wasm
VITE_CIRCT_BMC_JS_URL=/circt/circt-bmc.js
VITE_CIRCT_BMC_WASM_URL=/circt/circt-bmc.wasm
# VPI-capable circt-sim (for cocotb lessons — built with Asyncify + VPI exports):
VITE_CIRCT_SIM_VPI_JS_URL=/circt/circt-sim-vpi.js
VITE_CIRCT_SIM_VPI_WASM_URL=/circt/circt-sim-vpi.wasm
VITE_MOX_VERILOG_JS_URL=/mox/mox-verilog.js
VITE_MOX_VERILOG_WASM_URL=/mox/mox-verilog.wasm
VITE_MOX_SIM_JS_URL=/mox/mox-sim.js
VITE_MOX_SIM_WASM_URL=/mox/mox-sim.wasm
VITE_MOX_BMC_JS_URL=/mox/mox-bmc.js
VITE_MOX_BMC_WASM_URL=/mox/mox-bmc.wasm
# VPI-capable mox-sim (for cocotb lessons — built with Asyncify + VPI exports):
VITE_MOX_SIM_VPI_JS_URL=/mox/mox-sim-vpi.js
VITE_MOX_SIM_VPI_WASM_URL=/mox/mox-sim-vpi.wasm
# Pyodide URL (used by cocotb runner). Default is local: /pyodide/pyodide.js
# Optional CDN override:
# VITE_PYODIDE_URL=https://cdn.jsdelivr.net/pyodide/v0.27.0/full/pyodide.js
#
# Optional args for each stage (JSON array preferred):
# VITE_CIRCT_VERILOG_ARGS=[\"--ir-llhd\",\"--timescale\",\"1ns/1ns\",\"--single-unit\"]
# VITE_CIRCT_SIM_ARGS=[\"--resource-guard=false\"]
# VITE_CIRCT_BMC_ARGS=[\"--resource-guard=false\",\"-b\",\"3\",\"--module\",\"{top}\",\"--emit-smtlib\",\"-o\",\"-\",\"{input}\"]
# VITE_MOX_VERILOG_ARGS=[\"--ir-llhd\",\"--timescale\",\"1ns/1ns\",\"--single-unit\"]
# VITE_MOX_SIM_ARGS=[\"--resource-guard=false\"]
# VITE_MOX_BMC_ARGS=[\"--resource-guard=false\",\"-b\",\"3\",\"--module\",\"{top}\",\"--emit-smtlib\",\"-o\",\"-\",\"{input}\"]
24 changes: 12 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,24 @@ jobs:
- name: Setup Pyodide assets
run: scripts/setup-pyodide.sh

- name: Download CIRCT wasm artifacts
# WASM artifacts are built locally and published to the circt-wasm release
# via: npm run build:circt && npm run publish:circt
- name: Download MOX wasm artifacts
# WASM artifacts are built locally and published to the mox-wasm release
# via: npm run build:mox && npm run publish:mox
# CI just downloads the pre-built artifacts — no Emscripten build here.
run: |
mkdir -p static/circt
if gh release download circt-wasm \
mkdir -p static/mox
if gh release download mox-wasm \
--repo "$GITHUB_REPOSITORY" \
-D static/circt \
-D static/mox \
--clobber 2>/dev/null; then
if [ -f static/circt/uvm-core.tar.gz ]; then
rm -rf static/circt/uvm-core
tar -xzf static/circt/uvm-core.tar.gz -C static/circt
if [ -f static/mox/uvm-core.tar.gz ]; then
rm -rf static/mox/uvm-core
tar -xzf static/mox/uvm-core.tar.gz -C static/mox
fi
echo "CIRCT artifacts downloaded"
ls -lh static/circt/*.js
echo "MOX artifacts downloaded"
ls -lh static/mox/*.js
else
echo "::warning::No circt-wasm release found — WASM smoke tests will be skipped"
echo "::warning::No mox-wasm release found — WASM smoke tests will be skipped"
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
34 changes: 19 additions & 15 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,44 +39,48 @@ jobs:
- name: Download Pyodide assets
run: scripts/setup-pyodide.sh

- name: Download CIRCT wasm artifacts
# Artifacts are stored in a GitHub Release named 'circt-wasm'.
- name: Download MOX wasm artifacts
# Artifacts are stored in a GitHub Release named 'mox-wasm'.
# To publish them locally, run:
# gh release create circt-wasm --title "CIRCT WASM artifacts" \
# static/circt/circt-{bmc,sim,sim-vpi,verilog,lec}.{js,wasm} \
# gh release create mox-wasm --title "MOX WASM artifacts" \
# static/mox/mox-{bmc,sim,sim-vpi,verilog,lec}.{js,wasm} \
# /tmp/uvm-core.tar.gz
# where /tmp/uvm-core.tar.gz is created by:
# tar -czf /tmp/uvm-core.tar.gz -C static/circt uvm-core
# tar -czf /tmp/uvm-core.tar.gz -C static/mox uvm-core
# The build proceeds without them; simulation features will be
# unavailable but the rest of the tutorial still works.
run: |
mkdir -p static/circt
mkdir -p static/mox

unpack_uvm_bundle_if_present() {
if [ -f static/circt/uvm-core.tar.gz ]; then
rm -rf static/circt/uvm-core
tar -xzf static/circt/uvm-core.tar.gz -C static/circt
# Match uvm-core.tar.gz as well as older mis-named bundles such as
# uvm-core.XXXXXX.tar.gz (a past mktemp-template bug), newest first.
local bundle
bundle="$(ls -t static/mox/uvm-core*.tar.gz 2>/dev/null | head -1)"
if [ -n "$bundle" ]; then
rm -rf static/mox/uvm-core
tar -xzf "$bundle" -C static/mox
fi
}

have_uvm_bundle() {
[ -f static/circt/uvm-core/uvm-manifest.json ]
[ -f static/mox/uvm-core/uvm-manifest.json ]
}

if gh release download circt-wasm \
if gh release download mox-wasm \
--repo "$GITHUB_REPOSITORY" \
-D static/circt \
-D static/mox \
--clobber 2>/dev/null; then
unpack_uvm_bundle_if_present
echo "CIRCT artifacts downloaded from release 'circt-wasm'"
ls -lh static/circt/
echo "MOX artifacts downloaded from release 'mox-wasm'"
ls -lh static/mox/
if have_uvm_bundle; then
echo "UVM runtime bundle found"
else
echo "::notice::UVM runtime bundle missing (uvm-manifest.json not found); UVM lessons may fail."
fi
else
echo "::notice::No 'circt-wasm' release found; simulation features will be unavailable."
echo "::notice::No 'mox-wasm' release found; simulation features will be unavailable."
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
32 changes: 16 additions & 16 deletions .github/workflows/e2e-waveform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,27 @@ jobs:
- name: Prepare Surfer assets
run: scripts/setup-surfer.sh

- name: Ensure CIRCT wasm artifacts
id: circt_artifacts
- name: Ensure MOX wasm artifacts
id: mox_artifacts
run: |
mkdir -p static/circt
mkdir -p static/mox

have_all_artifacts() {
[ -f static/circt/circt-verilog.js ] && \
[ -f static/circt/circt-verilog.wasm ] && \
[ -f static/circt/circt-sim.js ] && \
[ -f static/circt/circt-sim.wasm ]
[ -f static/mox/mox-verilog.js ] && \
[ -f static/mox/mox-verilog.wasm ] && \
[ -f static/mox/mox-sim.js ] && \
[ -f static/mox/mox-sim.wasm ]
}

if have_all_artifacts; then
echo "ready=true" >> "$GITHUB_OUTPUT"
exit 0
fi

echo "Local CIRCT wasm artifacts missing; trying release 'circt-wasm'..."
if gh release download circt-wasm \
echo "Local MOX wasm artifacts missing; trying release 'mox-wasm'..."
if gh release download mox-wasm \
--repo "$GITHUB_REPOSITORY" \
-D static/circt \
-D static/mox \
--clobber 2>/dev/null; then
if have_all_artifacts; then
echo "ready=true" >> "$GITHUB_OUTPUT"
Expand All @@ -63,28 +63,28 @@ jobs:
fi

echo "ready=false" >> "$GITHUB_OUTPUT"
echo "::notice::Skipping waveform E2E: CIRCT wasm artifacts are missing (expected under static/circt or release circt-wasm)."
echo "::notice::Skipping waveform E2E: MOX wasm artifacts are missing (expected under static/mox or release mox-wasm)."
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Build app
if: steps.circt_artifacts.outputs.ready == 'true'
if: steps.mox_artifacts.outputs.ready == 'true'
run: npm run build

- name: Run unit tests
if: steps.circt_artifacts.outputs.ready == 'true'
if: steps.mox_artifacts.outputs.ready == 'true'
run: npm test

- name: Install Playwright browser
if: steps.circt_artifacts.outputs.ready == 'true'
if: steps.mox_artifacts.outputs.ready == 'true'
run: npx playwright install --with-deps chromium

- name: Run waveform E2E
if: steps.circt_artifacts.outputs.ready == 'true'
if: steps.mox_artifacts.outputs.ready == 'true'
run: npm run test:e2e -- e2e/waveform.spec.js

- name: Upload Playwright artifacts
if: always() && steps.circt_artifacts.outputs.ready == 'true'
if: always() && steps.mox_artifacts.outputs.ready == 'true'
uses: actions/upload-artifact@v4
with:
name: playwright-waveform-${{ github.run_id }}
Expand Down
26 changes: 13 additions & 13 deletions .github/workflows/uvm-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,37 +36,37 @@ jobs:
- name: Prepare Pyodide assets
run: scripts/setup-pyodide.sh

- name: Download CIRCT wasm artifacts
- name: Download MOX wasm artifacts
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir -p static/circt
mkdir -p static/mox

unpack_uvm_bundle_if_present() {
if [ -f static/circt/uvm-core.tar.gz ]; then
rm -rf static/circt/uvm-core
tar -xzf static/circt/uvm-core.tar.gz -C static/circt
if [ -f static/mox/uvm-core.tar.gz ]; then
rm -rf static/mox/uvm-core
tar -xzf static/mox/uvm-core.tar.gz -C static/mox
fi
}

have_all_artifacts() {
[ -f static/circt/circt-verilog.js ] && \
[ -f static/circt/circt-verilog.wasm ] && \
[ -f static/circt/circt-sim.js ] && \
[ -f static/circt/circt-sim.wasm ] && \
[ -f static/circt/uvm-core/uvm-manifest.json ]
[ -f static/mox/mox-verilog.js ] && \
[ -f static/mox/mox-verilog.wasm ] && \
[ -f static/mox/mox-sim.js ] && \
[ -f static/mox/mox-sim.wasm ] && \
[ -f static/mox/uvm-core/uvm-manifest.json ]
}

if ! have_all_artifacts; then
gh release download circt-wasm \
gh release download mox-wasm \
--repo "$GITHUB_REPOSITORY" \
-D static/circt \
-D static/mox \
--clobber
unpack_uvm_bundle_if_present
fi

if ! have_all_artifacts; then
echo "::error::CIRCT wasm artifacts are missing after release download."
echo "::error::MOX wasm artifacts are missing after release download."
exit 1
fi

Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ build.bak.*
*.swp

# Downloaded/built artifacts (run scripts/setup-*.sh to populate)
static/circt/
static/mox/
static/surfer/
static/pyodide/

Expand Down
2 changes: 1 addition & 1 deletion AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

## Resource Safety

- Treat `ninja`, `circt-sim`, large link steps, and similarly heavy tools as high-risk for local system stability.
- Treat `ninja`, `mox-sim`, large link steps, and similarly heavy tools as high-risk for local system stability.
- Always run heavy commands with explicit resource limits (for example: CPU parallelism limits, memory caps, and wall-clock timeouts).
- Prefer incremental/targeted builds over whole-tree builds when possible.
- Avoid running multiple heavy builds concurrently.
Expand Down
40 changes: 20 additions & 20 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ npm run dev # Start dev server (Vite)
npm run build # Production build
npm run preview # Preview production build

scripts/setup-circt.sh # Clone/update the CIRCT fork into vendor/circt
scripts/setup-circt.sh <dir> # Clone into a custom directory
scripts/setup-mox.sh # Clone/update the MOX fork into vendor/mox
scripts/setup-mox.sh <dir> # Clone into a custom directory

scripts/setup-surfer.sh # Download Surfer waveform viewer web build into public/surfer
scripts/setup-surfer.sh <dir> # Download into a custom directory
Expand All @@ -38,41 +38,41 @@ All state lives in the single root component. Key derived values:
- `completed = filesEqual(workspace, solutionFiles)` — drives the "solve"/"reset" toggle
- Lesson navigation mutates `lessonIndex`; reactive blocks reset `workspace`, `logs`, and `lastWaveform` on lesson change

### CIRCT WASM Runtime (`src/runtime/`)
### MOX WASM Runtime (`src/runtime/`)

Two files handle the runtime bridge:

**`circt-config.js`** — reads Vite env vars and resolves runtime configuration:
- `VITE_CIRCT_WASM_JS_URL` / `VITE_CIRCT_WASM_JS_URLS` — JS artifact URL(s) (comma-separated for fallback)
- `VITE_CIRCT_WASM_URL` / `VITE_CIRCT_WASM_URLS` — WASM artifact URL(s)
- `VITE_CIRCT_FACTORY_NAME` — optional Emscripten factory function name
- `VITE_CIRCT_TOOL_ARGS` — args for `run` (JSON array preferred, space-split fallback)
- `VITE_CIRCT_SELF_CHECK_ARGS` — args for the self-check smoke test
- Default JS candidates: `/circt/circt.js`, `/circt/circt-bmc.js`
- Default WASM candidates: `/circt/circt.wasm`, `/circt/circt-bmc.wasm`
**`mox-config.js`** — reads Vite env vars and resolves runtime configuration:
- `VITE_MOX_WASM_JS_URL` / `VITE_MOX_WASM_JS_URLS` — JS artifact URL(s) (comma-separated for fallback)
- `VITE_MOX_WASM_URL` / `VITE_MOX_WASM_URLS` — WASM artifact URL(s)
- `VITE_MOX_FACTORY_NAME` — optional Emscripten factory function name
- `VITE_MOX_TOOL_ARGS` — args for `run` (JSON array preferred, space-split fallback)
- `VITE_MOX_SELF_CHECK_ARGS` — args for the self-check smoke test
- Default JS candidates: `/mox/mox.js`, `/mox/mox-bmc.js`
- Default WASM candidates: `/mox/mox.wasm`, `/mox/mox-bmc.wasm`

**`circt-adapter.js`** — `CirctWasmAdapter` class, lazy-initialized on first `run()` or `selfCheck()`:
**`mox-adapter.js`** — `MoxWasmAdapter` class, lazy-initialized on first `run()` or `selfCheck()`:
- Tries each JS candidate URL in order until one loads successfully
- Detects runtime mode automatically:
- **`custom-runtime`**: `window.CIRCT_WASM_RUNTIME` global exposes `{ init, run, selfCheck? }`
- **`emscripten-module`**: raw Emscripten output; looks for factory functions (`createCirctBmcModule`, `createModule`, `Module`) then falls back to `window.Module`
- **`custom-runtime`**: `window.MOX_WASM_RUNTIME` global exposes `{ init, run, selfCheck? }`
- **`emscripten-module`**: raw Emscripten output; looks for factory functions (`createMoxBmcModule`, `createModule`, `Module`) then falls back to `window.Module`
- In Emscripten mode, files are written into the module's virtual FS under `/workspace/`, and output waveform is read back from `/workspace/out/waves.vcd`
- Arg templates support `{top}`, `{input}`, `{waveform}` placeholders

### CIRCT WASM Artifacts
### MOX WASM Artifacts

Place built artifacts from the CIRCT fork (`git@github.com:thomasnormal/circt.git`) at:
- `public/circt/circt-bmc.js` + `public/circt/circt-bmc.wasm`
- or custom shim: `public/circt/circt.js` + `public/circt/circt.wasm`
Place built artifacts from the MOX fork (`git@github.com:normal-computing/mox.git`) at:
- `public/mox/mox-bmc.js` + `public/mox/mox-bmc.wasm`
- or custom shim: `public/mox/mox.js` + `public/mox/mox.wasm`

Without these files, the runtime will fail gracefully with a log message directing you to run `scripts/setup-circt.sh`.
Without these files, the runtime will fail gracefully with a log message directing you to run `scripts/setup-mox.sh`.

### Surfer Waveform Viewer (`src/lib/components/WaveformViewer.svelte`)

The waveform pane embeds [Surfer](https://surfer-project.org/) via an `<iframe src="/surfer/">`.

- Surfer must be self-hosted (same origin) so that blob URLs created from in-memory VCD data are fetchable by the iframe.
- When CIRCT produces a VCD string (`lastWaveform.text`), the component creates a `Blob` → `URL.createObjectURL` and sends `{ command: 'LoadUrl', url }` via `postMessage` with progressive retries (0 / 800 / 2200 / 4500 ms) to absorb Surfer's WASM initialization time.
- When MOX produces a VCD string (`lastWaveform.text`), the component creates a `Blob` → `URL.createObjectURL` and sends `{ command: 'LoadUrl', url }` via `postMessage` with progressive retries (0 / 800 / 2200 / 4500 ms) to absorb Surfer's WASM initialization time.
- If `/surfer/index.html` is not found (HEAD 404), the component shows a prompt to run `scripts/setup-surfer.sh`.

Install artifacts:
Expand Down
4 changes: 2 additions & 2 deletions CURRICULUM.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Flag numbers identify the weak dimension(s): 1=Concept Focus, 2=Starter Calibrat
| Slug | Title | Status | Score | Prereqs | Teaches |
|---|---|---|---|---|---|
| `sva/implication` | Implication: \|->, \|=> | ✅ | 23/27 ⚠️5,8,9 | `sva/sequence-basics` | `\|->` (overlapping), `\|=>` (non-overlapping), antecedent/consequent |
| `sva/formal-intro` | Bounded Model Checking | ✅ | 22/27 ⚠️2,4,5,9 | `sva/implication` | BMC, `circt-bmc`, exhaustive proof vs simulation, bounded depth |
| `sva/formal-intro` | Bounded Model Checking | ✅ | 22/27 ⚠️2,4,5,9 | `sva/implication` | BMC, `mox-bmc`, exhaustive proof vs simulation, bounded depth |

### Chapter: Core Sequences
| Slug | Title | Status | Score | Prereqs | Teaches |
Expand Down Expand Up @@ -193,7 +193,7 @@ Flag numbers identify the weak dimension(s): 1=Concept Focus, 2=Starter Calibrat
> match — unlike `|->` / `|=>` which pass vacuously.
> Exercise: compare the two forms on a burst read; observe the `#=#`
> failure when the burst never occurs vs the `|=>` silent pass.
> *Requires circt-bmc for the formal comparison half.*
> *Requires mox-bmc for the formal comparison half.*

---

Expand Down
Loading
Loading