{"id":26012494,"url":"https://github.com/ethanuppal/marlin","last_synced_at":"2026-05-02T07:11:24.325Z","repository":{"id":272200800,"uuid":"912564904","full_name":"ethanuppal/marlin","owner":"ethanuppal","description":"🦀 No nonsense hardware testing/simulation in Rust 🛠️ | Verilog, Spade, Veryl","archived":false,"fork":false,"pushed_at":"2025-04-05T01:52:16.000Z","size":2660,"stargazers_count":41,"open_issues_count":14,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T19:16:37.837Z","etag":null,"topics":["hardware","rust","simulation","testbench","testing","verilator","verilog"],"latest_commit_sha":null,"homepage":"https://www.ethanuppal.com/marlin/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ethanuppal.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-05T23:16:12.000Z","updated_at":"2025-04-08T22:23:12.000Z","dependencies_parsed_at":"2025-03-26T23:25:13.247Z","dependency_job_id":"5802d31b-4b7b-418d-b42c-51b21975b838","html_url":"https://github.com/ethanuppal/marlin","commit_stats":null,"previous_names":["ethanuppal/dumbname","ethanuppal/marlin"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethanuppal%2Fmarlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethanuppal%2Fmarlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethanuppal%2Fmarlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ethanuppal%2Fmarlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ethanuppal","download_url":"https://codeload.github.com/ethanuppal/marlin/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248094988,"owners_count":21046770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hardware","rust","simulation","testbench","testing","verilator","verilog"],"created_at":"2025-03-06T00:32:34.096Z","updated_at":"2026-05-02T07:11:24.319Z","avatar_url":"https://github.com/ethanuppal.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# marlin 🐟\n\n[![CI Badge](https://github.com/ethanuppal/marlin/actions/workflows/ci.yaml/badge.svg)](https://github.com/ethanuppal/marlin/blob/main/.github/workflows/ci.yaml)\n[![Code Style Badge](https://github.com/ethanuppal/marlin/actions/workflows/lint.yaml/badge.svg)](https://github.com/ethanuppal/marlin/blob/main/.github/workflows/lint.yaml)\n[![Crates.io Version](https://img.shields.io/crates/v/marlin)](https://crates.io/crates/marlin)\n[![docs.rs](https://img.shields.io/docsrs/marlin)](https://docs.rs/marlin/latest/marlin)\n[![Crates.io License](https://img.shields.io/crates/l/marlin)](./LICENSE)\n[![Supported Spade version](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fgithub.com%2Fethanuppal%2Fmarlin%2Fraw%2Frefs%2Fheads%2Fmain%2FCargo.toml\u0026query=workspace.dependencies.spade-parser.version\u0026label=Spade)](https://github.com/ethanuppal/marlin/blob/main/language-support/spade)\n[![Supported Veryl version](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fgithub.com%2Fethanuppal%2Fmarlin%2Fraw%2Frefs%2Fheads%2Fmain%2FCargo.toml\u0026query=workspace.dependencies.veryl-parser.version\u0026label=Veryl)](https://github.com/ethanuppal/marlin/blob/main/language-support/veryl)\n[![Matrix](https://img.shields.io/matrix/marlin-project%3Amatrix.org?label=Matrix)](https://matrix.to/#/#marlin-project:matrix.org)\n\n**[Read the documentation](https://ethanuppal.com/marlin)** | **[Read the API reference](https://docs.rs/marlin/latest/marlin)**\n\nMarlin is a really powerful library (and API) that lets you \"import\" hardware\nmodules into Rust (or Rust functions into hardware modules!). \n\nNo precompilation step and manual updates with `verilator` harnesses; no \nMakefiles and quirky decorators with `cocotb` testbenches. You're writing a regular Rust crate here.\n\nAdd this library to your `Cargo.toml` like any other library. Use hardware\nmodules as `struct`s like any other Rust `struct`. Hook them up to `tokio` or\n`serde` even. `cargo test` as hard as you want.\n\nMarlin works out of the box on macOS and Linux (verified under continuous integration).\n\n![Early example of using this with Spade](./assets/demo-alpha.png)\n\n\u003e [!NOTE]\n\u003e The above screenshot is pre-0.1.0, so it's a bit out of date -- Marlin has\n\u003e improved a lot since then!\n\n## Motivation\n\nWhy does hardware testing suck? Consider the ways we have to test\n(System)Verilog:\n\n- **Test natively**: Verilog is already a terrible enough language, and writing\n  tests *in* Verilog is really annoying.\n- **Use Verilator harnesses**: You have to first run Verilator to get the right\n  headers, recompile manually every time, deal with raw pointers and C++, etc.\n- **Use cocotb**: You have to use Makefiles or write your own Python runner, \n  performance isn't the greatest, you get no LSP support for ports, etc.\n\nThe problem gets worse with custom HDLs, so they've come up with some creative\nsolutions:\n\n- [Calyx](https://calyxir.org): the canonical way of testing Calyx code is to\n  read from JSON files representing byte arrays and write to JSON files\n  representing byte arrays.\n- [Spade](https://spade-lang.org): `verilator` integration involves [absurd\n  macro magic](https://docs.spade-lang.org/simulation.html#verilator) and [using\n  `cocotb`](https://docs.spade-lang.org/simulation.html#cocotb) requires putting the design-under-test in a code comment.\n- [Veryl](https://veryl-lang.org): you literally [write inline Verilog or Python](https://doc.veryl-lang.org/book/05_language_reference/13_integrated_test.html). Yes, inside Veryl code.\n\nStill, a lot of these are less than optimal.\n\n## Features\n\n- Minimal overhead over directly using `verilator`\n- Works completely drop-in in your existing projects\n- Safe VCD tracing support\n- Declarative API for usability + Dynamic API for programmability\n- DPI support in Rust: call Rust functions from (System)Verilog\n- Integration with modern HDLs\n- Rust. Did I say Rust?\n\n## Requirements\n\n- [Rust](https://rustup.rs), 2021 edition\n- [`verilator`](https://verilator.org/guide/latest/install.html), 5.025 or later\n  - Earlier versions may work but are not tested\n- [GNU Make](https://www.gnu.org/software/make/)\n- A C++ compiler that `verilator` can find; may need to [support at least C++14](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf).\n\n## Install\n\nMarlin is on [crates.io], so just use `cargo add --dev marlin` to add Marlin as a\ndependency for your tests (`dev-dependencies`).\n\n## How it works\n\nI'll write more on this once I get further in the development process.\nThe TLDR is procedural macros + `dlopen`.\nThere are some stub pages in the work-in-progress internal section of the documentation, such as [this page](https://www.ethanuppal.com/marlin/internal/how-it-works.html).\n\n### Hardware simulation tools are slow! How does Marlin deal with that?\n\nSimulation tools take an _absurd_ amount of time to run.\nFor example, when you use Marlin in a Spade project, it calls out to:\n\n- `swim build`, which recompiles the entire Spade compiler from source\n- `verilator`, which compiles and links C++ code\n\nMarlin automatically runs them with all the right flags and arguments\n--- and it caches and only invokes them when needed.\n\n## Related\n\n- [verilated-rs](https://github.com/djg/verilated-rs) is a super cool library\n  that uses a build script to statically link in verilated bindings, but is\n  unmaintained for years as of writing this.\n\n## License \u0026 Legal\n\n[![cargo-deny badge](https://github.com/ethanuppal/marlin/actions/workflows/cargo-deny.yaml/badge.svg)](https://github.com/ethanuppal/marlin/blob/main/.github/workflows/cargo-deny.yaml)\n\nMarlin is licensed under the Mozilla Public License 2.0. This license is\nsimilar to the Lesser GNU Public License, except that the copyleft applies only\nto the source code of this library, not any library that uses it. That means you\ncan statically or dynamically link with unfree code (see\n\u003chttps://www.mozilla.org/en-US/MPL/2.0/FAQ/#virality\u003e).\n\nI use [`cargo-deny`](https://github.com/EmbarkStudios/cargo-deny) (see the\n[`deny.toml`](./deny.toml)) to ensure no licensing violations occur. I also\ncheck this on CI to prevent merging any new dependencies or dependency updates\nthat introduce incompatible licenses.\n\n### Large Language Models\n\nI do not permit any contributions containing output, in part or in whole, from large language models (LLMs) or other probabilistic models.\n\n### Verilator\n\nVerilator is licensed under the Lesser GNU General Public License 3.0. However,\nMarlin will `dlopen` Verilated code, which is permitted via this clause:\n\n\u003e 1) Use a suitable shared library mechanism for linking with the\n\u003e   Library.  A suitable mechanism is one that (a) uses at run time\n\u003e   a copy of the Library already present on the user's computer\n\u003e   system, and (b) will operate properly with a modified version\n\u003e   of the Library that is interface-compatible with the Linked\n\u003e   Version.\n\nThrough [`VerilatorRuntimeOptions::verilator_executable`](https://docs.rs/marlin/latest/marlin/verilator/struct.VerilatorRuntimeOptions.html#structfield.verilator_executable),\nyou can specify your own interface-compatible Verilator wrapper, enabling (b).\n\n[crates.io]: https://crates.io/crates/marlin\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=ethanuppal/marlin\u0026type=date\u0026legend=top-left)](https://www.star-history.com/#ethanuppal/marlin\u0026type=date\u0026legend=top-left)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fethanuppal%2Fmarlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fethanuppal%2Fmarlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fethanuppal%2Fmarlin/lists"}