diff --git a/.editorconfig b/.editorconfig index 0020fc03ac..f15441abf8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,12 @@ root = true [*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true indent_style = space indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..e0642e80bc --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# Default review ownership for GhostRoboticsLab/rp2350js_emulator. +# @prat96 (Pratheek Balakrishna) is requested on every PR; under the +# GhostRoboticsLab org this is the catch-all owner for anything without a +# more specific rule below. +* @prat96 diff --git a/.github/ISSUE_TEMPLATE/01-isa-instruction-bug.yml b/.github/ISSUE_TEMPLATE/01-isa-instruction-bug.yml new file mode 100644 index 0000000000..bdfe2bc8b6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/01-isa-instruction-bug.yml @@ -0,0 +1,82 @@ +name: "RISC-V instruction / ISA incorrectness" +description: "An instruction decodes, traps, or computes a result that disagrees with the RISC-V spec or Hazard3." +title: "[isa] " +labels: ["bug", "riscv-core"] +body: + - type: markdown + attributes: + value: | + Thanks for stress-testing the Hazard3 core. + + **Before you file:** + - Search [existing issues](https://github.com/GhostRoboticsLab/rp2350js_emulator/issues?q=is%3Aissue) — this is an **early-but-real** fork and known gaps are tracked in [ROADMAP.md](https://github.com/GhostRoboticsLab/rp2350js_emulator/blob/main/ROADMAP.md). + - This template is for a *single wrong instruction*: a bad decode, a wrong result word, a mis-targeted trap, a missing CSR side effect. The core is `RV32IMAC + Zba/Zbb/Zbs/Zcb`; the M-extension family (incl. `MULHSU`), trap entry, and the Hazard3 IRQ controller were the largest fix areas — see [README.md](https://github.com/GhostRoboticsLab/rp2350js_emulator/blob/main/README.md#what-this-fork-fixes-in-the-risc-v-core). + - For a whole peripheral or a firmware that won't boot, use the *Peripheral / firmware boot issue* template instead. + - type: input + id: instructions + attributes: + label: "Affected instruction(s)" + description: "Mnemonic(s), exactly as the assembler spells them. If you have the 16/32-bit encoding, include it." + placeholder: "MULHSU, or c.zext.h, or csrrc — encoding 0x02C5_A5B3 if known" + validations: + required: true + - type: dropdown + id: isa-area + attributes: + label: "ISA area" + description: "Which extension or subsystem the instruction belongs to." + options: + - "RV32I (base integer)" + - "RV32M (mul/div)" + - "RV32A (atomics)" + - "RV32C (compressed)" + - "Zba/Zbb/Zbs (bit-manipulation)" + - "Zcb (extra compressed)" + - "Zicsr (CSR access)" + - "trap / CSR machine state (mtvec, mcause, mstatus, mepc, …)" + - "Xh3irq (Hazard3 interrupt controller: meinext, meiea, meipa, …)" + - "other / not sure" + validations: + required: true + - type: textarea + id: expected-vs-actual + attributes: + label: "Expected vs actual" + description: "What the spec says should happen, and what the engine does instead. Be exact: operand values, the result word, the resulting PC, or mcause/mepc for a trap." + placeholder: | + Inputs: rs1 = 0xFFFF_FFFF (-1, signed), rs2 = 0x0000_0002 (2, unsigned) + Expected (MULHSU = signed*unsigned, high word): 0xFFFF_FFFF + Actual: 0x0000_0001 + validations: + required: true + - type: textarea + id: reproducer + attributes: + label: "Minimal reproducer" + description: "Smallest asm sequence (the in-tree assembler is fine) or a firmware ELF/UF2 plus the steps to reach the faulting instruction. Paste the snippet; attach the binary if needed." + placeholder: | + li a0, -1 + li a1, 2 + mulhsu a2, a0, a1 # a2 should be 0xFFFFFFFF + # then: dump x12 after one step + render: text + validations: + required: true + - type: checkboxes + id: negative-control + attributes: + label: "Regression test" + description: "Every core fix in this repo ships with a falsifiable test in src/riscv/test/cpu-fixes.spec.ts that is proven to FAIL on the pre-fix engine (a negative control). It speeds up triage enormously if you can supply one." + options: + - label: "I can/will add a negative-control test (an assertion proven to fail on the current engine)." + required: false + - label: "I confirmed this isn't already a deferred item in ROADMAP.md (e.g. the intentional illegal-instruction `throw`)." + required: false + - type: input + id: version + attributes: + label: "Engine version / commit" + description: "The release tag (e.g. rp2350-v0.1.0) or `git rev-parse --short HEAD`. Note: v0.1.0..v1.3.3 are inherited upstream rp2040js tags, not this fork's releases." + placeholder: "rp2350-v0.1.0 / fb7f130" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/02-peripheral-or-firmware.yml b/.github/ISSUE_TEMPLATE/02-peripheral-or-firmware.yml new file mode 100644 index 0000000000..03fcfb627b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02-peripheral-or-firmware.yml @@ -0,0 +1,77 @@ +name: "Peripheral / firmware boot issue" +description: "A RP2350 peripheral behaves wrong, or a real firmware won't boot / hangs / produces the wrong output." +title: "[peripheral] " +labels: ["bug", "rp2350-peripheral"] +body: + - type: markdown + attributes: + value: | + Thanks for running real firmware through the chip. + + **Before you file:** + - Search [existing issues](https://github.com/GhostRoboticsLab/rp2350js_emulator/issues?q=is%3Aissue) first. The peripheral layer is freshly multi-chip parameterized and some RP2350 PIO features are **deliberately deferred** until firmware exercises them — check the "remaining RP2350 PIO features" section of [ROADMAP.md](https://github.com/GhostRoboticsLab/rp2350js_emulator/blob/main/ROADMAP.md) before reporting a PIO gap (`IN_COUNT` masking, PIO IRQ-index mode, neighbour-SM restart, `FJOIN_RX/TX`, `WAIT PIN` gpiobase offset are known-deferred). + - Three firmware integration tests are known-good baselines: `blink_simple` (GPIO via SIO), `hello_timer` (250M-step timer-IRQ run, 19 prints), `pio_blink` (two PIO blocks, GPIO3 + GPIO32 via the GPIOBASE pin-window). If yours diverges from one of these, say which. + - If the root cause is a single wrong *instruction*, use the *RISC-V instruction / ISA incorrectness* template instead. + - type: dropdown + id: peripheral + attributes: + label: "Peripheral" + description: "The block most likely at fault. Pick `bootrom` if the chip never reaches your firmware's entry point." + options: + - "SIO (single-cycle IO, GPIO atomic set/clr/xor)" + - "TIMER" + - "PIO" + - "DMA" + - "GPIO / pads (function-select, pad mask, GPIOBASE pin-window)" + - "UART" + - "SPI" + - "I2C" + - "PWM" + - "ADC" + - "USB" + - "RESETS (reset_mask / RESET_DONE)" + - "POWMAN" + - "bootrom (A2)" + - "other / not sure" + validations: + required: true + - type: textarea + id: firmware + attributes: + label: "Firmware under test" + description: "What is it, and how was it built? SDK version, target board, RISC-V vs Arm toolchain. Link or attach the ELF/UF2 if you can." + placeholder: | + pico-sdk 2.1.0, board pico2 (rp2350, riscv), pio_ws2812 example driving GP28. + Built with the riscv toolchain; attaching ws2812.elf. + validations: + required: true + - type: textarea + id: expected-vs-actual + attributes: + label: "What happens vs what you expected" + description: "Observed behaviour against intended. Be concrete: which GPIO/register, expected vs actual value, where it hangs (PC, the spin loop), or how the output stream differs." + placeholder: | + Expected: GP28 emits a 24-bit WS2812 frame, GP3 toggles twice. + Actual: chip spins in the bootrom RESET_DONE loop and never reaches main(). + validations: + required: true + - type: textarea + id: repro + attributes: + label: "Steps to reproduce" + description: "Exactly how you ran it: the harness/script, step budget, and what you inspected. A minimal failing snippet beats a prose description." + placeholder: | + 1. const mcu = new RP2350(); load ws2812.uf2; mcu.core0.pc = 0x... + 2. step ~2,000,000 cycles + 3. read gpioValues — GP28 never changes + render: text + validations: + required: true + - type: input + id: version + attributes: + label: "Engine version / commit" + description: "The release tag (e.g. rp2350-v0.1.0) or `git rev-parse --short HEAD`. (v0.1.0..v1.3.3 are inherited upstream rp2040js tags, not this fork's.)" + placeholder: "rp2350-v0.1.0 / fb7f130" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/03-bug-report.yml b/.github/ISSUE_TEMPLATE/03-bug-report.yml new file mode 100644 index 0000000000..3d658ba7fd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/03-bug-report.yml @@ -0,0 +1,52 @@ +name: "Bug report" +description: "Anything wrong that isn't a single ISA instruction or a specific peripheral/firmware boot — tooling, build, test harness, assembler, API." +title: "[bug] " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for the report. + + **Before you file:** + - Search [existing issues](https://github.com/GhostRoboticsLab/rp2350js_emulator/issues?q=is%3Aissue). + - If this is a wrong RISC-V instruction, or a peripheral/firmware boot problem, the two dedicated templates collect the right details faster. + - Pure RP2040 (Arm) issues that also reproduce on upstream belong at [wokwi/rp2040js](https://github.com/wokwi/rp2040js/issues). + - type: textarea + id: summary + attributes: + label: "What's wrong" + description: "A clear, concrete description of the bug and where it surfaces (build, lint, a vitest case, the assembler, the public API, …)." + validations: + required: true + - type: textarea + id: repro + attributes: + label: "Steps to reproduce" + description: "Minimal steps or a snippet. `npm install` then the exact command you ran (e.g. `npx vitest run src/riscv`)." + render: text + validations: + required: true + - type: textarea + id: expected + attributes: + label: "Expected behaviour" + description: "What you expected to happen instead." + validations: + required: true + - type: textarea + id: logs + attributes: + label: "Logs / output" + description: "Relevant error text, stack trace, or failing test output. Will be rendered as code — no backticks needed." + render: shell + validations: + required: false + - type: input + id: environment + attributes: + label: "Environment" + description: "Node version (CI runs 20 and 22; the project needs >=18), OS, and the engine version/commit (`git rev-parse --short HEAD`)." + placeholder: "Node 22, macOS 15, rp2350-v0.1.0 / fb7f130" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/04-feature-request.yml b/.github/ISSUE_TEMPLATE/04-feature-request.yml new file mode 100644 index 0000000000..90ce196048 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/04-feature-request.yml @@ -0,0 +1,45 @@ +name: "Feature request / enhancement" +description: "Propose a new capability — an unimplemented RP2350 peripheral feature, an ISA extension, tooling, or an API improvement." +title: "[feature] " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Thanks for helping shape the fork. + + **Check [ROADMAP.md](https://github.com/GhostRoboticsLab/rp2350js_emulator/blob/main/ROADMAP.md) first.** Several RP2350 features are *already designed and deliberately deferred* — they'll land each with its own falsifiable test rather than be ported unverified. If your request is one of these (e.g. PIO `IN_COUNT` masking, PIO IRQ-index mode / `resolveIrqTarget`, neighbour state-machine synchronous restart, `FJOIN_RX/TX` joined FIFOs, the `WAIT PIN` gpiobase offset, or the intentional illegal-instruction `throw`), please **upvote / comment** rather than open a duplicate, and tell us the firmware that needs it — firmware-driven demand is what moves a deferred item up the list. + - type: textarea + id: problem + attributes: + label: "Problem / motivation" + description: "What can't you do today, and what firmware or use case needs it? Concrete beats abstract." + placeholder: "My firmware joins the PIO TX FIFO (FJOIN_TX) for a 8-deep DMA-fed stream; the engine only offers a 4-deep FIFO, so the program underruns." + validations: + required: true + - type: textarea + id: proposal + attributes: + label: "Proposed behaviour" + description: "What should the engine do? Reference the relevant register/instruction/bitfield if you know it (e.g. SHIFTCTRL.FJOIN_TX, GPIOBASE, MEINEXT)." + validations: + required: true + - type: dropdown + id: roadmap-check + attributes: + label: "ROADMAP.md status" + description: "Where does this sit relative to the roadmap?" + options: + - "Already listed as deferred in ROADMAP.md (I'm adding demand/context)" + - "Not on the roadmap — genuinely new" + - "Not sure" + validations: + required: true + - type: textarea + id: test + attributes: + label: "How would we know it works?" + description: "This fork gates every behaviour with a falsifiable test. Sketch the assertion or the firmware run that would prove the feature correct (and ideally fail on today's engine)." + placeholder: "A PIO test that fills 8 TX words after FJOIN_TX and asserts no underrun over N cycles; fails today because the FIFO caps at 4." + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..365aa4ed88 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: "RP2040-only (Arm) issue" + url: "https://github.com/wokwi/rp2040js/issues" + about: "This fork's contribution is the RP2350 / Hazard3 RISC-V side. A bug that reproduces on plain RP2040 belongs upstream at wokwi/rp2040js." + - name: "Questions & ideas" + url: "https://github.com/GhostRoboticsLab/rp2350js_emulator" + about: "Not sure it's a bug? Read the README and open a Discussion (or a thread on the repo) rather than an issue." diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..7b71f06479 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +## What & why + + + +Closes # + +## Checklist + +- [ ] Where behavior changed, a regression test was added and **PROVEN to fail on the pre-fix engine** (negative control — see `src/riscv/test/cpu-fixes.spec.ts`). +- [ ] `npm test` is green (348+ tests, 0 skipped). +- [ ] `npx tsc --noEmit` is clean. +- [ ] prettier + eslint clean (`npm run format:check` && `npm run lint`). +- [ ] DCO sign-off present on every commit (`git commit -s`); no co-author trailers. +- [ ] For any imported code, original authorship and [CREDITS.md](../CREDITS.md) are preserved. +- [ ] [ROADMAP.md](../ROADMAP.md) / [CHANGELOG.md](../CHANGELOG.md) updated if this lands or defers a tracked item. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..675563dec6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,30 @@ +# Dependabot config — batched, monthly, low-noise. +# Minor + patch bumps are grouped into a single PR per ecosystem; majors come +# through on their own so they get individual review. +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 5 + labels: + - "dependencies" + groups: + npm-minor-patch: + update-types: + - "minor" + - "patch" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 5 + labels: + - "dependencies" + groups: + actions-minor-patch: + update-types: + - "minor" + - "patch" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..b7777e0110 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,79 @@ +# Changelog + +All notable changes to this fork are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +Releases here are fork-namespaced (`rp2350-vX.Y.Z`). The inherited `v0.1.0`..`v1.3.3` +tags belong to upstream [wokwi/rp2040js](https://github.com/wokwi/rp2040js) and are +**not** this fork's releases. + +## [Unreleased] + +Nothing yet. + +## [rp2350-v0.1.0] - 2026-06-28 + +First fork-namespaced release: c1570's RP2350 / Hazard3 RISC-V core, re-based onto +the latest upstream wokwi/rp2040js and corrected until the chip boots its A2 bootrom +and runs real firmware. **348 tests pass, 0 skipped.** See [CREDITS.md](./CREDITS.md) +for lineage and [ROADMAP.md](./ROADMAP.md) for what remains deferred. + +### Added + +- Imported c1570's RP2350 / Hazard3 RISC-V engine (the CPU and assembler under + `src/riscv/*`, the RP2350 chip in `rp2350.ts` / `rpchip.ts`, and the RP2350 + peripheral variants `*_rp2350.ts`), with c1570's commit authorship preserved. +- Three firmware integration tests against the A2 bootrom: + - **`blink_simple`** — GPIO driven via SIO. + - **`hello_timer`** — a 250M-step run driven by RP2350 timer interrupts + (~22 s; exactly 19 timer-driven prints). + - **`pio_blink`** — two PIO blocks driving GPIO3 and GPIO32, the latter through + the RP2350 GPIOBASE pin-window. +- RP2350 PIO **GPIOBASE** pin-window: register `0x168` (`gpiobase = value & 16`) + re-bases a PIO block's internal 32-pin window onto chip GPIO16..47, with the + matching `checkChangedPins` offset so GPIO16..47 are actually notified. +- Fork identity: GitHub Actions CI (Node 20 + 22), [CREDITS.md](./CREDITS.md), + [ROADMAP.md](./ROADMAP.md), [README.md](./README.md), and the demo firmware + fixtures the integration tests run. +- Digital-twin hero light-show GIFs and docs (the `ghostshow` firmware stepped + through the RP2350 bootrom, SIO, timers, and PIO). + +### Changed + +- Adapted the imported engine to upstream's NodeNext ESM module resolution. +- Parameterized the peripheral layer to be multi-chip: `RP2040` and `RP2350` both + implement a shared **`IRPChip`** interface, peripherals depend on `IRPChip` + instead of the concrete chip, and `GPIOPin` delegates function-select dispatch + to the chip. `npx tsc --noEmit` is now clean (was 63 errors). +- Widened the PIO pad mask to 32 bits for the RP2350 (`isRp2040 ? 0x3fffffff : + 0xffffffff`); upstream hardcoded the RP2040 30-bit mask. + +### Fixed + +- **RV32M multiply family.** `MUL`/`MULH`/`MULHU` are now exact via + `Math.imul` / `BigInt` (the old float64 `*` was wrong above 2⁵³); **`MULHSU` + was undecoded and crashed the core** and is now implemented. +- **Synchronous trap entry.** `ECALL`/`EBREAK` no longer skip the handler's first + instruction (they previously landed at `mtvec + ilen`). +- **Hazard3 external IRQ 0** (TIMER0) is now delivered (NOIRQ is tested via the + `MEINEXT` sign bit, not `irq == 0`). +- **Base-ISA defects:** `SLTIU` immediate sign-extension, `JALR` LSB masking, + `CSRRC` write gating, warm-reset PC restore, and the trap-entry `mstatus` + update (clear only MIE, preserve MPP). +- **Zcb** compressed instructions the RP2350 bootrom needs. +- **`MEINEXT` reset value** (found by lockstepping against c1570's engine): it now + resets to NOIRQ, so the IRQ-0 gate no longer takes a *phantom* IRQ 0 the instant + firmware enables interrupts (this was the `hello_timer` stall). +- **`MTVEC` mode-bit masking** (also found by lockstepping): trap targets now mask + `mtvec[1:0]`, so a vectored mtvec (RP2350 firmware sets `0x20000001`) no longer + sends an exception to an odd address and crashes (this was the `pio_blink` crash). + +Each fix above is guarded by a falsifiable regression test in +[`src/riscv/test/cpu-fixes.spec.ts`](./src/riscv/test/cpu-fixes.spec.ts), proven to +fail on the pre-fix engine (a negative control). One deferral is kept on purpose: +the illegal-instruction `throw` remains a debug aid rather than `mcause = 2`. + +[Unreleased]: https://github.com/GhostRoboticsLab/rp2350js_emulator/compare/rp2350-v0.1.0...HEAD +[rp2350-v0.1.0]: https://github.com/GhostRoboticsLab/rp2350js_emulator/releases/tag/rp2350-v0.1.0 diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000000..51507d5e29 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,38 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it using these metadata." +title: "rp2350js — RP2350 (Hazard3 RISC-V) emulator" +abstract: "A TypeScript emulator of the RP2350 (Raspberry Pi Pico 2) Hazard3 RISC-V cores. A fork of wokwi/rp2040js that re-bases c1570's RP2350 work onto the latest upstream and corrects the RISC-V core (RV32IMAC + Zba/Zbb/Zbs/Zcb), test-gated against a falsifiable instruction-correctness suite and three firmware integration tests." +type: software +authors: + - family-names: Balakrishna + given-names: Pratheek +repository-code: "https://github.com/GhostRoboticsLab/rp2350js_emulator" +url: "https://github.com/GhostRoboticsLab/rp2350js_emulator" +license: MIT +version: rp2350-v0.1.0 +date-released: "2026-06-28" +keywords: + - rp2350 + - risc-v + - hazard3 + - emulator + - raspberry-pi-pico-2 + - digital-twin + - embedded + - typescript +references: + - type: software + title: "rp2040js" + abstract: "The RP2040 emulator base this fork builds on." + authors: + - family-names: Shaked + given-names: Uri + url: "https://github.com/wokwi/rp2040js" + license: MIT + - type: software + title: "rp2040js (rp2350js/WIP branch) — RP2350 / Hazard3 RISC-V core" + abstract: "The original RP2350 / Hazard3 RISC-V emulation core, imported here with authorship preserved." + authors: + - name: "c1570" + url: "https://github.com/c1570/rp2040js" + license: MIT diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..b3f8216810 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,132 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +pratheekb96@gmail.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..52b28ef728 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,102 @@ +# Contributing + +Thanks for wanting to help. This fork takes c1570's RP2350 / Hazard3 RISC-V work, re-bases it onto +the latest upstream [wokwi/rp2040js](https://github.com/wokwi/rp2040js), and hardens it. Contributions +that move that forward are welcome. + +## What fits + +- **RISC-V correctness.** Bugs in the Hazard3 core — RV32IMAC + Zba/Zbb/Zbs/Zcb, the CSRs, trap entry, + the Xh3irq external-interrupt controller. Found one? See [The core principle](#the-core-principle). +- **RP2350 peripherals.** The peripheral layer is now multi-chip parameterized against `IRPChip`; the + next concrete worklist is the deferred RP2350 PIO features (`IN_COUNT` masking, PIO IRQ-index mode, + neighbour-SM synchronous restart, `FJOIN_RX`/`FJOIN_TX`, the `WAIT PIN` gpiobase offset). Each is + spelled out in **[ROADMAP.md](./ROADMAP.md)**. +- **Firmware integration tests.** New real-firmware runs that exercise a path the unit suite can't — + in the spirit of `blink_simple`, `hello_timer`, and `pio_blink`. +- **Upstreamable refactors.** Each peripheral's parameterization is a natural small PR back to Wokwi. + Keep that path open — see the upstreaming plan at the end of **[ROADMAP.md](./ROADMAP.md)**. + +If you're unsure whether something fits, open an issue first (see [Reporting & asking](#reporting--asking)). + +## The core principle + +**Every behavioral fix ships with a falsifiable test that is proven to fail on the pre-fix engine — a +negative control.** This is the project's signature rule. The 19 audit defects and the two trap bugs +each landed this way; without it, a "fix" is just a claim. + +A green test on the fixed engine proves nothing on its own — it might be green by accident, or testing +the wrong thing. The negative control closes that gap: the test must be **red on the old behavior and +green on the new one**, so it pins down exactly the behavior you changed. + +How to author one: + +1. Write the test to assert the **correct** result, with the **specific** operands or register state + that triggers the bug. Be concrete — e.g. a `MULHSU` of operands whose product crosses 2⁵³, an + `ECALL` checking the handler runs its *first* instruction (PC == `mtvec`, not `mtvec + ilen`), a + trap target masking `MTVEC[1:0]`, a `MEINEXT` reset value of NOIRQ. +2. **Confirm red before the fix.** Run it against the unfixed engine and watch it fail. If it passes, + it isn't exercising the bug — fix the test, not the engine. +3. **Confirm green after the fix.** Apply the change; the same test now passes. + +Unit-level fixes go in +[`src/riscv/test/cpu-fixes.spec.ts`](./src/riscv/test/cpu-fixes.spec.ts). Behavior that only surfaces +under a real firmware run (like the `MEINEXT` and `MTVEC` trap bugs, found by lockstepping against +c1570's engine and bisecting the first divergence) goes in a firmware-integration test instead. + +One deferral is kept on purpose: the illegal-instruction `throw` is a debug aid, not a silent +`mcause=2` trap. Don't "fix" it without discussion. + +## Dev setup + +```bash +git clone https://github.com/GhostRoboticsLab/rp2350js_emulator +cd rp2350js_emulator +npm install # Node >= 18 +npm test # 348 pass, 0 skipped. hello_timer takes ~22s (a 250M-step firmware run). +``` + +The RISC-V correctness suite alone: + +```bash +npx vitest run src/riscv +``` + +`npx tsc --noEmit` must stay clean — it is (was 63 errors before the peripheral parameterization). +Don't regress it. + +## Code style + +prettier + eslint are enforced via `lint-staged` + `husky`, and run automatically on commit. To check +by hand: + +```bash +npm run lint +npm run format:check +``` + +## Commits & PRs + +- **Short imperative subjects**, matching the existing history (e.g. `Port RP2350 PIO GPIOBASE + pin-window; pio_blink now passes`). +- **DCO sign-off is required** — commit with `git commit -s`, which adds a + `Signed-off-by: Name ` trailer. **No co-author trailers anywhere.** +- Work through the [pull-request template](./.github/PULL_REQUEST_TEMPLATE.md) checklist before + opening a PR. +- **Keep PRs small and reviewable.** One concern per PR — this mirrors the upstreaming philosophy of + offering work back to Wokwi as small, ordered PRs rather than one large drop. + +## Credit & lineage + +This codebase is the third link in a chain of MIT-licensed work (see **[CREDITS.md](./CREDITS.md)**). +When you touch imported code: + +- **Preserve original authorship.** c1570's RP2350 / Hazard3 work was imported with commit authorship + intact; keep it that way. +- **Keep [CREDITS.md](./CREDITS.md) and [LICENSE](./LICENSE) intact** in any derivative. + +## Reporting & asking + +- File bugs and requests through the [issue templates](./.github/ISSUE_TEMPLATE/) — they prompt for + the specifics (failing test, instruction, register state) that make a report actionable. +- All participation is under the [Code of Conduct](./CODE_OF_CONDUCT.md). diff --git a/README.md b/README.md index 9bc6622289..100223eb20 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -![CI](../../actions/workflows/ci.yml/badge.svg) +[![CI](../../actions/workflows/ci.yml/badge.svg)](../../actions/workflows/ci.yml) +[![Tests](https://img.shields.io/badge/tests-348%20passing-brightgreen.svg)](#quick-start) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) +[![Node](https://img.shields.io/badge/node-%E2%89%A518-339933.svg?logo=node.js&logoColor=white)](./package.json) +[![TypeScript](https://img.shields.io/badge/TypeScript-ESM-3178c6.svg?logo=typescript&logoColor=white)](#layout) +[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md) # rp2350js — RP2350 (Hazard3 RISC-V) emulator diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..fa31470f84 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,90 @@ +# Security Policy + +`rp2350js` is a development-time, instruction-level emulator of the RP2350 (Hazard3 RISC-V) +that **executes arbitrary firmware binaries inside a Node.js process on your machine**. That +is its job. This file states what it does and does not defend against, what counts as a +security issue here, and how to report one. + +## Scope & threat model (read this first) + +This is a **digital twin for bringing up firmware**, not a security sandbox. It steps the +Hazard3 core through the RP2350 bootrom and your firmware to surface a wrong `MUL` or a dropped +timer IRQ as a red test — see [README.md](./README.md) and [ROADMAP.md](./ROADMAP.md). It is +**not** an isolation boundary. + +Concretely: + +- The emulated guest (firmware) runs in the **same OS process** as the emulator host. There is + no syscall filter, no separate address space, no capability drop, no resource cap. The guest + is confined only by the correctness of the host code that models the machine. +- A firmware image is **code you are choosing to run on your computer**, with whatever access + the Node process has. Treat running a firmware binary in this emulator exactly as you would + treat running any other untrusted program locally. +- **Do not run untrusted firmware expecting isolation.** If you need to contain a hostile + binary, run the emulator itself inside a real sandbox (container, VM, locked-down user) — the + emulator does not provide one. + +Within that honest boundary, the host code should still be sound: a correct emulator must not +let the modeled machine reach beyond the modeled machine. + +## What is a security issue here vs. a normal bug + +A **security issue** is a defect in the **host** (the TypeScript/Node emulator process), for +example: + +- A memory-safety / host-impact defect in host code — an unbounded read or write into host + memory, a crash or hang reachable from emulated state that a normal firmware run can trigger, + unbounded host resource consumption driven by guest behavior. +- A guest that can affect the **host beyond the emulated machine** — escaping the modeled + address space, reaching the host filesystem, network, environment, or process outside the + documented emulation surface; influencing the host beyond producing emulated outputs. +- A vulnerable dependency (a CVE in a package we ship) that is actually reachable in how this + project uses it. + +A **normal bug** is wrong *emulation*, and belongs in the +[issue tracker](https://github.com/GhostRoboticsLab/rp2350js_emulator/issues), not here: + +- "Firmware misbehaves" or "the emulated result is wrong" — a mis-decoded instruction, an + off-by-one in a peripheral, a wrong CSR value (`MTVEC`, `MEINEXT`, `GPIOBASE`), an + `MULHSU`/`MULH` precision error, a missed IRQ, a PIO pin-window mismatch. These are + correctness defects in the *guest model*. They are exactly the class of bug this fork exists + to find and fix (see [README.md](./README.md)), but they are not security vulnerabilities — + a wrong emulated result does not, by itself, cross the host boundary. File one as a normal + issue with a falsifiable repro, ideally a failing test in the style of + [`src/riscv/test/cpu-fixes.spec.ts`](./src/riscv/test/cpu-fixes.spec.ts). + +If you are unsure which category a finding falls in, report it privately (below) and we will +triage it. + +## Supported versions + +Security fixes target the current fork release line only. The `v0.1.0..v1.3.3` tags are +inherited from upstream wokwi/rp2040js and are **not** this fork's releases (see +[CREDITS.md](./CREDITS.md)); they are not separately supported here. + +| Version | Supported | +|---|---| +| `rp2350-v0.1.x` (this fork) | ✅ | +| inherited pre-fork tags (`v0.1.0`..`v1.3.3`) | ❌ — report upstream to [wokwi/rp2040js](https://github.com/wokwi/rp2040js) | + +## Reporting a vulnerability + +**Preferred:** use GitHub private vulnerability reporting — go to the repository +[**Security** tab](https://github.com/GhostRoboticsLab/rp2350js_emulator/security) and choose +**"Report a vulnerability"**. This keeps the report private until a fix is ready. + +**Fallback:** email the maintainer at **pratheekb96@gmail.com**. + +Please do **not** open a public issue for a suspected vulnerability. + +A useful report includes: the version or commit, the host platform and Node version (CI runs +Node 20 and 22; the project requires Node >= 18), the firmware or input that triggers it, and +the observed host-side impact (crash, host read/write, resource exhaustion, escape). + +What to expect: + +- **Acknowledgement within 7 days** of your report. +- Coordinated disclosure: we will work with you on a fix and a disclosure timeline, and credit + you in the release notes / [CHANGELOG.md](./CHANGELOG.md) unless you ask us not to. +- No bug-bounty program, and no legal action against good-faith research that stays within this + policy. diff --git a/docs/social-preview.png b/docs/social-preview.png new file mode 100644 index 0000000000..5396dc6e02 Binary files /dev/null and b/docs/social-preview.png differ diff --git a/package.json b/package.json index a0a4cd1b0c..905cf2bd68 100644 --- a/package.json +++ b/package.json @@ -6,18 +6,34 @@ "type": "git", "url": "git+https://github.com/GhostRoboticsLab/rp2350js_emulator.git" }, + "homepage": "https://ghostlabs.web.app", + "bugs": { + "url": "https://github.com/GhostRoboticsLab/rp2350js_emulator/issues" + }, "keywords": [ "rp2350", "rp2040", "raspberry pi pico 2", + "pico2", "hazard3", "risc-v", - "emulator" + "rv32imac", + "emulator", + "simulator", + "microcontroller", + "embedded", + "digital-twin", + "pio", + "typescript" ], "files": [ "dist" ], "author": "Uri Shaked ", + "contributors": [ + "c1570 (RP2350 / Hazard3 RISC-V emulation core)", + "Pratheek Balakrishna (RP2350 RISC-V fixes, upstream port)" + ], "license": "MIT", "type": "module", "main": "./dist/cjs/index.js",