{"slug": "tiny-vedas-a-generic-accelerator-interface-for-risc-v-from-pytorch-op-to-gds", "title": "Tiny-Vedas: a generic accelerator interface for RISC-V, from PyTorch op to GDS", "summary": "Tiny Vedas released an open-source RISC-V AI accelerator stack whose shipping RTL is a 4-stage pipelined RV32IM processor in SystemVerilog paired with an 8×8 int8 GEMM MMIO accelerator sharing DCCM over AXI4, with PyVedas compiling torch.compile output to C and then to RV32 ELF for on-core inference kernels. The repo also ships a Python instruction-set simulator for RTL trace comparison, YAML-driven decode tables, and an optional sv2v plus OpenROAD ASIC flow for core_gemm_top, while presets for VLIW, superscalar, and out-of-order variants are scaffolded but only rv32im_scalar matches implemented RTL today. The project is used as a reference for a free course on RISC-V Processor Design.", "body_md": "Tiny Vedas is an open-source stack for designing, verifying, and bringing up RISC-V AI accelerators — from synthesizable processor RTL and spec-driven decode, through ISS/RTL co-simulation, to a PyTorch JIT that targets bare-metal firmware on the core.\n\n**Today**, the repo ships a complete **RV32IM** reference core: a 4-stage in-order pipeline with Harvard memory, hazard handling, and end-to-end test infrastructure. **Next**, the same contracts extend to additional microarchitectures (VLIW, superscalar, out-of-order) and vector units — hardware presets and software hooks are already scaffolded in [`hw/`](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/hw/README.md) so RTL, simulation, and PyVedas can evolve together without breaking the workflow.\n\nIt is also used as a reference for the [free course on RISC-V Processor Design](https://youtu.be/izPdo7n1uI).\n\n| Layer | Role | \n|---|---|\n| **RTL** | Synthesizable RISC-V cores, GEMM accelerator, and SoC integration ( `rtl/` ) | \n| **Verification** | Python ISS + RTL trace comparison ( `tools/rv_iss.py` ,`sim_manager.py` ); GEMM directed/random co-sim (`tools/gemm_cosim.py` ) | \n| **Decode** | YAML-driven instruction tables → SystemVerilog ( `open-decode-tables/` ) | \n| **Primitives** | Reusable arithmetic and register blocks ( `SVLib/` ) | \n| **Software** | Bare-metal runtime, printf, assembly/C/PyTorch tests | \n| **PyVedas** | `torch.compile` → C → RV32 ELF for on-core inference kernels | \n| **PD** | Optional ASIC flow: sv2v + OpenROAD ( `pd/` ) —`core_gemm_top` (CPU + GEMM) | \n\nThe shipping RTL is a **4-stage pipelined RV32IM** processor written in SystemVerilog, plus an **8×8 int8 GEMM** MMIO accelerator that shares DCCM over AXI4. The CPU flavor (`hw/presets/rv32im_scalar.yaml`) is the baseline used by CI, examples, and the course.\n\nTiny Vedas is built to support **multiple CPU organizations** behind one hardware-config contract. Presets in [`hw/presets/`](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/hw/presets) already describe scalar, VLIW, superscalar, and out-of-order variants with optional vector units; only `rv32im_scalar` matches implemented RTL today. As new microarchitectures land, `sim_manager`, PyVedas, and the test suite will target them through the same `--hw-config` YAML — so accelerator exploration stays one toolchain, not a fork per design.\n\n- **ISA** : RISC-V RV32IM (32-bit integer + multiply/divide)\n- **Pipeline** : 4-stage (IFU → IDU0 → IDU1 → EXU)\n- **Memory** : Harvard architecture — separate ICCM and DCCM (true dual-port, both ports RW). The core keeps custom fetch/LSU ports;`soc_top` and the FPGA SoC convert those to**AXI4** (32-bit, ID width 4, two DCCM masters) into on-chip CCM slaves. FPGA muxes DCCM port B between the core and the host (halt-and-load). ASIC PD synthesizes`core_gemm_top` (CPU + GEMM; memories stay off-chip IOs).\n- **GEMM** : Output-stationary 8×8 PE array (`int8 × int8 → int32` , K-tile 32) at`MMIO_GEMM_ADDR` (`0x00300000` ). Packed AXI4 INCR DMA loads A/B from DCCM and writes C; the core is held via`accel_hold` for the duration of one START job (software does not poll DONE).\n- **Decode** : Spec-driven via the`open-decode-tables` submodule (YAML → SystemVerilog)\n- **Verification** : Python instruction-set simulator (ISS) compared against RTL traces\n\n- **Arithmetic** : ADD, SUB, ADDI, LUI, AUIPC\n- **Logical** : AND, OR, XOR, ANDI, ORI, XORI\n- **Shifts** : SLL, SRL, SRA, SLLI, SRLI, SRAI\n- **Comparison** : SLT, SLTU, SLTI, SLTIU\n- **Branches** : BEQ, BNE, BLT, BGE, BLTU, BGEU\n- **Jumps** : JAL, JALR\n- **Memory** : LB, LH, LW, LBU, LHU, SB, SH, SW\n- **Multiply/Divide** : MUL, MULH, MULHU, MULHSU, DIV, DIVU, REM, REMU\n- **System** : NOP (`addi x0, x0, 0` ), ECALL (decoded; no trap handler yet — behaves as NOP)\n\n- Register forwarding from EXU to IDU1\n- Pipeline flush on taken branches and jumps\n- Register scoreboard for RAW hazard detection\n- Multi-cycle multiplier and divider\n- Booth-encoded 32×32 multiplier with per-operand signedness (MUL / MULH / MULHU / MULHSU)\n- Non-restoring divider with combinational Kogge-Stone adders on the iteration path\n- Unaligned load/store support with byte-strobe DCCM writes (no store RMW) and strobe-aware store-to-load forwarding. Dual RW DCCM ports complete both beats of an unaligned access in one cycle (stall only on a same-cycle load/store port conflict).\n\nOne START programs a single 2-D DCCM matrix multiply `C = A × B`:\n\n| Item | Value | \n|---|---|\n| Array | 8×8 output-stationary PEs | \n| Datatypes | `int8 × int8 → int32` accumulators | \n| K tiling | 32-element tiles, dual ping-pong A/B buffers | \n| DMA | 32-bit AXI4 INCR bursts (A along K, B along N, C int32 along N) | \n| Wait | Core `accel_hold` for the job; tests must not poll STATUS before reading C | \n\nCSRs (`rtl/include/gemm_csrs.svh`): `BASE_A/B/C`, `M`, `N`, `K`, `CTRL` (START / soft reset), `STATUS` (BUSY / DONE). DONE is sticky until the next START. Firmware examples: `tests/asm/gemm_8x8.s`, `tests/c/gemm_8x8.c`, `tests/c/gemm_multi.c`.\n\n```\nTiny-Vedas/\n├── rtl/                     # Processor + accelerator RTL\n│   ├── core_top.sv          # CPU pipeline (memory ports exposed)\n│   ├── soc_top.sv           # core_top + GEMM + AXI4 adapters + ICCM/DCCM\n│   ├── core_top.flist       # Sim file list (core + SoC + bus + GEMM)\n│   ├── accel/               # GEMM MMIO engine (CSR, DMA, 8×8 PE array)\n│   │   ├── gemm_top.sv      # Job FSM + ping-pong tile orchestration\n│   │   ├── gemm_csr.sv      # AXI-Lite CSRs at 0x00300000\n│   │   ├── gemm_dma.sv      # Packed AXI4 INCR bursts to DCCM\n│   │   ├── gemm_datapath.sv # Systolic array + accumulators\n│   │   └── gemm_pe.sv       # int8 MAC PE\n│   ├── bus/                 # AXI4 fetch/LSU masters, CCM slaves, master mux\n│   ├── ifu/                 # Instruction fetch unit\n│   ├── idu/                 # Decode stages, regfile, scoreboard\n│   │   ├── rv32im_decoder.sv   # Generated — do not hand-edit\n│   │   └── decode_out_t.svh      # Generated — do not hand-edit\n│   ├── exu/                 # ALU, MUL, DIV, LSU\n│   ├── include/             # global.svh, types.svh, axi4.svh, gemm_csrs.svh, mmio_map.svh\n│   └── lib/                 # Byte-write ICCM/DCCM (`sync_tdp_mem`)\n├── fpga/alveo_u280/         # Alveo U280 bitstream, host load, card smoke\n├── pd/                      # ASIC PD: sv2v + OpenROAD (`core_gemm_top`)\n│   ├── rtl/core_gemm_top.sv # PD wrapper: core_top + gemm_top\n│   ├── platforms/           # ASAP7 / sky130 YAML\n│   └── README.md\n├── dv/\n│   ├── sv/                  # core_top_tb.sv, gemm_top_tb.sv, lsu_tb.sv\n│   └── verilator/           # Verilator C++ harness\n├── hw/                      # Hardware presets (scalar, VLIW, OoO + vector)\n│   ├── presets/             # YAML configs shared by RTL/SW (see hw/README.md)\n│   ├── soc/                 # SoC device map (UART, GEMM, EOT)\n│   └── types.py             # Typed HwConfig loader\n├── tests/\n│   ├── asm/                 # Assembly test programs (incl. gemm_8x8)\n│   ├── c/                   # C tests (helloworld, iaxpy, gemm_8x8, gemm_multi)\n│   ├── elf/                 # Prebuilt ELF binaries (dhrystone)\n│   ├── pyvedas/             # PyTorch → JIT model specs (incl. gemm_mmio)\n│   ├── smoke.tlist          # Regression test list\n│   └── gemm.tlist           # GEMM-only regression\n├── pyvedas/                 # PyTorch → Tiny-Vedas JIT\n├── tools/\n│   ├── sim_manager.py       # Main test runner (compile → ISS → RTL → compare)\n│   ├── rv_iss.py            # Reference instruction-set simulator\n│   └── gemm_cosim.py        # Directed / random GEMM co-simulation\n├── sw/\n│   ├── include/             # soc_defines.h (generated — do not hand-edit)\n│   └── vedas_printf/        # Bare-metal printf library for C tests\n├── SVLib/                   # Git submodule — reusable SystemVerilog primitives\n├── open-decode-tables/      # Git submodule — YAML decode table generator\n├── scripts/\n│   ├── install_deps.sh      # Dependency installer (`make deps`)\n│   ├── env.sh               # Generated PATH + venv (by `make deps`)\n│   ├── with_env.sh          # Wrapper used by Makefile targets\n│   └── pd_docker.sh         # OpenROAD Docker wrapper for rtl2gds\n├── .github/workflows/ci.yml # GitHub Actions CI pipeline\n├── Makefile\n├── requirements.txt\n└── LICENSE\n```\n\n| Tool | Purpose | \n|---|---|\n| **Verilator** | RTL simulation (primary; used in CI) | \n| **riscv64-unknown-elf-gcc** | Bare-metal cross-compiler for test programs (RV32IM / ILP32) | \n| **Python 3** | `sim_manager.py` ,`rv_iss.py` , decode generation | \n| **Xilinx Vivado** (optional) | XSim simulation — only needed if you prefer `make smoke` over Verilator | \n\nTested on Ubuntu 22.04 and 24.04. Other Linux distributions should work with equivalent packages installed manually.\n\n```\ngit clone --recurse-submodules https://github.com/siliscale/Tiny-Vedas.git\ncd Tiny-Vedas\n```\n\nIf you already cloned without submodules:\n\n```\ngit submodule update --init --recursive\n```\n\nOn Ubuntu, `make deps` installs everything needed for simulation and verification:\n\n- System build packages (`build-essential` , Verilator build deps)\n- Python virtual environment with packages from `requirements.txt`\n- Prebuilt **RISC-V GNU bare-metal toolchain** (`riscv64-unknown-elf-gcc` ) into`.local/riscv/`\n- Latest stable Verilator compiled from source into `.local/verilator/`\n\n```\nmake deps\n```\n\n`make deps` also generates `scripts/env.sh` (PATH + venv) and verifies the toolchain. All Makefile test targets use it automatically via `scripts/with_env.sh`, so CI and local runs work without manual setup.\n\nFor interactive shells, source the environment once per session:\n\n```\nsource scripts/env.sh\nriscv64-unknown-elf-gcc --version\nverilator --version\n```\n\nOverride pinned versions if needed:\n\n```\nRISCV_TOOLCHAIN_VERSION=2026.06.05 make deps   # default\nVERILATOR_TAG=v5.048 make deps                   # pin a specific Verilator release\nFORCE_RISCV_TOOLCHAIN_REINSTALL=1 make deps      # re-download toolchain\nFORCE_VERILATOR_REBUILD=1 make deps              # rebuild Verilator\n```\n\nDo **not** run `make deps` with `sudo` — only the apt step needs elevated privileges. If a previous `sudo make deps` left `deps/verilator` root-owned, fix ownership then rebuild:\n\n```\nsudo chown -R \"$USER:$USER\" deps/verilator\nFORCE_VERILATOR_REBUILD=1 make deps\n# Verilator (recommended; same as CI)\nmake smoke-verilator\n\n# Xilinx XSim (requires Vivado — optional)\nmake smoke\n./tools/sim_manager.py -s verilator -n asm.basic_alu_r\n./tools/sim_manager.py -s verilator -n c.helloworld\n./scripts/with_env.sh ./tools/sim_manager.py -s verilator -n pyvedas.vector_add\n```\n\nTiny Vedas compiles bare-metal test programs with `riscv64-unknown-elf-gcc` using `-march=rv32im -mabi=ilp32`. Do **not** use the Linux cross-compiler (` riscv64-linux-gnu-gcc`) or distribution packages that lack newlib — they will not produce working bare-metal ELFs.\n\n`make deps` downloads a prebuilt **riscv64-unknown-elf** toolchain from the [riscv-collab/riscv-gnu-toolchain releases](https://github.com/riscv-collab/riscv-gnu-toolchain/releases) page and installs it to `.local/riscv/`. The Ubuntu series (22.04 or 24.04) is detected automatically.\n\n1. Go to [riscv-gnu-toolchain releases](https://github.com/riscv-collab/riscv-gnu-toolchain/releases) .\n2. Download the **`riscv64-elf-ubuntu-<version>-gcc.tar.xz`** archive matching your Ubuntu version.\n3. Extract and add to your `PATH` :\n\n```\n# Example for Ubuntu 22.04, release 2026.06.05\nwget https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2026.06.05/riscv64-elf-ubuntu-22.04-gcc.tar.xz\nmkdir -p ~/.local\ntar -xJf riscv64-elf-ubuntu-22.04-gcc.tar.xz -C ~/.local\n\n# Add to ~/.bashrc\nexport PATH=\"$HOME/.local/riscv/bin:$PATH\"\nsource ~/.bashrc\n```\n\n1. Verify RV32IM support:\n\n```\nriscv64-unknown-elf-gcc --version\necho 'int main(void) { return 0; }' | riscv64-unknown-elf-gcc -march=rv32im -mabi=ilp32 -nostdlib -x c -\n```\n\nIf prebuilt binaries are unavailable for your platform, follow the build instructions in the [riscv-gnu-toolchain README](https://github.com/riscv-collab/riscv-gnu-toolchain). Configure for bare metal:\n\n```\n./configure --prefix=/opt/riscv --with-arch=rv32im --with-abi=ilp32\nmake -j$(nproc)\n```\n\nThis takes a long time. Prefer the prebuilt nightly releases for development and CI.\n\nAll tests are driven by `tools/sim_manager.py`. Tests are named `<type>.<name>`:\n\n| Prefix | Source | Example | \n|---|---|---|\n| `asm.` | `tests/asm/<name>.s` | `asm.basic_mul` | \n| `c.` | `tests/c/<name>.c` | `c.helloworld` | \n| `elf.` | `tests/elf/<name>` (prebuilt) | `elf.dhrystone` | \n| `pyvedas.` | `tests/pyvedas/<name>.py` (JIT → ELF) | `pyvedas.vector_add` | \n\n```\n./scripts/with_env.sh ./tools/sim_manager.py -s <simulator> (-n <test> | -t <task-list>)\n\n  -s, --simulator   verilator | xsim\n  -n, --test-name   Run a single test (e.g. asm.basic_alu_r)\n  -t, --task-list   Run all tests listed in a file (e.g. tests/smoke.tlist)\n  --hw-config       Hardware preset YAML (default: hw/presets/rv32im_scalar.yaml)\n  --vcd             Verilator waveform (core_top.vcd); omit for smoke/CI\n```\n\n`make smoke-verilator` and `make smoke` invoke `with_env.sh` automatically.\n\n| Target | Command | \n|---|---|\n| `make deps` | Install system packages, Python venv, RISC-V toolchain, and Verilator | \n| `make smoke-verilator` | Run the smoke regression via Verilator (CI default) | \n| `make smoke` | Run the smoke regression via XSim (requires Vivado) | \n| `make fpga alveo_u280` | Build the Alveo U280 bitstream (Vivado 2023.2) | \n| `make fpga_smoke alveo_u280` | Run `tests/smoke.tlist` on the programmed Alveo (needs sudo) | \n| `make gemm-directed` | Directed GEMM RTL vs golden ( `tools/gemm_cosim.py` ) | \n| `make gemm-cosim` | Directed + 100 random GEMM seeds | \n| `make rtl2gds` | ASIC PD: sv2v + OpenROAD ( `core_gemm_top` ; see[pd/README.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/pd/README.md) ) | \n| `make decodes` | Regenerate `rtl/idu/rv32im_decoder.sv` from YAML | \n| `make soc` | Regenerate `mmio_map.svh` and`sw/include/soc_defines.h` from`hw/soc/` | \n| `make clean` | Remove build artifacts ( `work/` ,`obj_dir/` , logs, VCDs) | \n\nEach test writes artifacts to `work/<test>/`:\n\n| File | Contents | \n|---|---|\n| `iss.log` | Golden ISS execution trace | \n| `rtl.log` | RTL architectural trace | \n| `sim.log` | Simulator stdout and comparison errors | \n| `console.log` | Program UART output | \n| `stats.txt` | IPC/CPI performance metrics | \n| `core_top.vcd` | Waveform (Verilator `--vcd` only; off by default) | \n\nTiny Vedas uses **co-simulation**: a Python ISS generates a golden trace, the RTL simulator produces its own trace, and `sim_manager.py` compares them instruction by instruction (PC, opcode, register writes, memory stores, branches).\n\nPrograms signal completion by storing `EOT_MAGIC` (`0xdeadbeef`) to `MMIO_EOT_ADDR` (`0x10000000`). See `tests/asm/eot_sequence.s` and `sw/include/soc_defines.h`.\n\nThe multiply unit is a **Booth-encoded** 32×32 multiplier. Operands enter at EXU\nstage e2; the 64-bit product is registered at e3 and written when sideband\nlatency (`MUL_LAT`) expires.\n\n| RV32M instruction | rs1 sign | rs2 sign | \n|---|---|---|\n| MUL, MULH | signed | signed | \n| MULHU | unsigned | unsigned | \n| MULHSU | signed | unsigned | \n\nInside `mul`, the **signed operand is always the multiplicand** and the\n**unsigned operand is Booth-scanned as the multiplier**. When rs1 is unsigned\nand rs2 is signed, operands are swapped (product is commutative). Separate\ncontrols drive multiplicand sign extension (`mc_sign`) and unsigned-multiplier\ncorrection (`mult_unsign`); a single global unsigned flag is not sufficient for\nMULHSU.\n\nPipeline placement is configured in `rtl/include/mul_pd_config.svh` (included by\n`exu_mul`). At most **one** internal register stage should be enabled for PD\nexperiments — see [pd/README.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/pd/README.md).\n\n**Final CPA** (`CPA_ALGORITHM` on SVLib `mul`):\n\n| Value | Module | Notes | \n|---|---|---|\n| `0` | `adder_pipe` + RCA | `PIPE_STAGES_CPA` splits width | \n| `1` | `adder_pipe` + 4-bit CLA | Default for generic builds | \n| `2` | `kogge_stone_pipe` | 2-cycle CPA, **one flop** mid prefix tree; production`exu_mul` uses this | \n\n| Path | When | Latency | \n|---|---|---|\n| **Fast** | Divide by zero/one, zero dividend, signed overflow, or both magnitudes ≤4 bits ( `small_div` ) | 1 cycle after issue | \n| **Slow** | Everything else — 32-step non-restoring divider on absolute magnitudes | ~33 cycles | \n\nThe slow path uses **combinational** `kogge_stone_adder` instances for the\nper-iteration trial add/subtract and remainder correction. Do **not** use\n`kogge_stone_pipe` here — that module has a pipeline register and is reserved\nfor the multiplier CPA.\n\n| Module | Registers | Use | \n|---|---|---|\n| `adder` | No | Generic wrapper: `ALGORITHM` 0=RCA, 1=CLA, 2=Kogge-Stone (comb.) | \n| `kogge_stone_adder` | No | Combinational Kogge-Stone prefix adder (power-of-2 width) | \n| `kogge_stone_pipe` | One | Pipelined Kogge-Stone (prefix tree split across two cycles) | \n| `adder_pipe` | Optional | Multi-lane pipelined CPA for non-Kogge multiplier configs | \n\nSee [SVLib/README.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/SVLib/README.md) for the full library inventory.\n\nSmoke tests cover ALU, forwarding, multiply, divide (`asm.basic_div`,\n`asm.div_regression`), load/store, branches, jumps, C programs, PyVedas JIT tests\n(`pyvedas.{vector,matrix,tensor}_{add,mul}`), GEMM (` asm.gemm_8x8`, `c.gemm_8x8`,\n`c.gemm_multi`, `pyvedas.gemm_mmio`), and Dhrystone. `tests/gemm.tlist` runs the\nGEMM subset alone.\n\n| Memory | Depth | Width | Notes | \n|---|---|---|---|\n| ICCM (instructions) | 2^18 words | 32-bit | Loaded from ELF `.text` section | \n| DCCM (data) | 2^18 words | 32-bit | Dual RW ports (byte strobes); loaded from `.data` ,`.rodata` ,`.bss` , etc. | \n\nConfigured in `rtl/include/global.svh`. The Alveo overlay uses smaller windows (32 KiB ICCM / 1 MiB DCCM, BAR2 2 MiB); see [fpga/alveo_u280/README.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/fpga/alveo_u280/README.md). UART (`0x00200000`), GEMM (` 0x00300000`), and EOT (` 0x10000000`) writes are decoded on the core store path and do not enter DCCM as MMIO. Addresses come from [`hw/soc/default.yaml`](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/hw/soc/default.yaml); software uses generated [`sw/include/soc_defines.h`](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/sw/include/soc_defines.h).\n\n| Address | Purpose | \n|---|---|\n| `SOC_LINK_ADDRESS` (`0x00100000` ) | Default link address for test programs ( `-Wl,-Ttext=0x100000` ) | \n| `MMIO_UART_ADDR` (`0x00200000` ) | MMIO UART — bare-metal `printf` output (`sw/vedas_printf` ) | \n| `MMIO_GEMM_ADDR` (`0x00300000` ) | GEMM CSRs (BASE_A/B/C, M/N/K, CTRL, STATUS) — see `rtl/include/gemm_csrs.svh` | \n| `MMIO_EOT_ADDR` (`0x10000000` ) | End-of-test flag — write `EOT_MAGIC` to halt simulation | \n| `0x80000000` | Default initial stack pointer (register x2) | \n\nThe reset vector is taken from the ELF `_start` symbol, not hardcoded.\n\nInstruction decode logic is generated from YAML, not hand-written. The source of truth is `open-decode-tables/tables/rv32im.yaml`.\n\n```\nmake decodes\n```\n\nThis regenerates:\n\n- `rtl/idu/rv32im_decoder.sv`\n- `rtl/idu/decode_out_t.svh`\n\nTo add or modify instructions, edit the YAML in the `open-decode-tables` submodule, commit and push there, then update the submodule pointer in this repo and run `make decodes`.\n\nMMIO devices (UART, GEMM, EOT) are described in `hw/soc/default.yaml`, not hardcoded in RTL or C. CPU presets select the map with `soc: default`.\n\n```\nmake soc\n```\n\nThis regenerates:\n\n- `rtl/include/mmio_map.svh` — address ranges and indices for`rtl/bus/mmio_mux.sv`\n- `sw/include/soc_defines.h` — C / preprocessed`.S` macros (`MMIO_UART_ADDR` ,`EOT_MAGIC` , …)\n- `sw/include/soc_defines.inc` — gas`.include` for`.s` tests\n\n`sim_manager.py` runs the same generation at the start of a test. To add a device, edit the YAML and re-run `make soc`. Bare-metal software includes `soc_defines.h` and uses the generated macros — see `sw/vedas_printf/vedas_printf.c`.\n\nCreate `tests/asm/my_test.s`:\n\n```\n    .globl   _start\n    .section .text\n\n_start:\n    li   x1, 42\n    add  x2, x1, x1\n    .include \"eot_sequence.s\"\n```\n\nRun with:\n\n```\n./tools/sim_manager.py -s verilator -n asm.my_test\n```\n\nCreate `tests/c/my_test.c` using `vedas_printf` for output. `sim_manager.py` compiles `sw/vedas_printf/vedas_printf.c` alongside the test with `-march=rv32im -mabi=ilp32 -nostdlib -lgcc` (required by the prebuilt bare-metal toolchain). The end-of-test sequence comes from `tests/c/asm_functions/eot_sequence.s`.\n\nPyVedas tests are **model spec files** under `tests/pyvedas/`. Each file describes a small `torch.compile` module and concrete trace inputs. `sim_manager.py` JIT-compiles the model to C, links it with the PyVedas runtime, builds an RV32 ELF, and runs the usual ISS/RTL comparison.\n\n**Prerequisites:** run `make deps` once — it installs CPU PyTorch into the repo `venv/` (used automatically by `sim_manager.py`). For JIT-only debugging you can also use `pyvedas/.venv`; see [pyvedas/README.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/pyvedas/README.md).\n\nCreate `tests/pyvedas/my_add.py`:\n\n``` python\n\"\"\"PyVedas smoke test: elementwise add.\"\"\"\n\nimport torch\n\nclass MyAdd(torch.nn.Module):\n    def forward(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:\n        return x + y\n\nMODEL = torch.compile(MyAdd())\nTRACE_INPUTS = (\n    torch.tensor([1, 2, 3, 4], dtype=torch.int32),\n    torch.tensor([10, 20, 30, 40], dtype=torch.int32),\n)\n```\n\n| Symbol | Purpose | \n|---|---|\n| `MODEL` | `torch.compile` module exported by the JIT | \n| `TRACE_INPUTS` | Tuple of concrete tensors — used for `torch.export` tracing**and** to bake static buffer values into`generated.c` | \n\n**Constraints today**\n\n- Use **`torch.int32`** tensors (bare-metal target has no soft-float).\n- Every graph op must have a **1:1 entry** in`pyvedas/runtime/ops.yaml` with a matching C kernel (e.g.`aten.add.Tensor` ,`aten.mul.Tensor` ). Adding a new op requires a registry entry and runtime implementation — see[pyvedas/README.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/pyvedas/README.md) .\n\nRun with:\n\n```\n./scripts/with_env.sh ./tools/sim_manager.py -s verilator -n pyvedas.my_add\n```\n\nAdd the test name to `tests/smoke.tlist` to include it in `make smoke-verilator`:\n\n```\npyvedas.my_add\n```\n\n**What happens under the hood**\n\n1. JIT (`pyvedas/jit` ) exports the graph and writes`work/pyvedas.my_add/generated.c` ,`graph.txt` , and`manifest.json` .\n2. The RISC-V linker builds `test.elf` from`generated.c` , runtime sources from the manifest, and`eot_sequence.s` .\n3. ISS and Verilator traces are compared like any other test.\n\nInspect JIT output on failure: `work/pyvedas.my_add/jit.log`, `compile.log`, `sim.log`.\n\nThe core and GEMM are synthesizable. Simulation and FPGA SoCs sit **outside**\n`core_top`: AXI4 adapters, ICCM/DCCM slaves, and `gemm_top` (`rtl/bus/`,\n`rtl/accel/`, `rtl/soc_top.sv`, `fpga/alveo_u280/rtl/`). ASIC PD nets\n`core_gemm_top` (CPU + GEMM, memories as IOs) — see [pd/README.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/pd/README.md).\nFPGA build/program/smoke:\n\n```\nmake fpga alveo_u280          # bitstream (Vivado 2023.2)\nmake fpga_smoke alveo_u280    # PCIe load + EOT on the card (sudo)\n```\n\nFor ASIC physical design (SystemVerilog → Verilog via\n[sv2v](https://github.com/zachjs/sv2v), then OpenROAD-flow-scripts), see\n[pd/README.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/pd/README.md):\n\n```\nmake config                    # CPU flavor + PDK platform\nmake sv2v                      # convert RTL only\nmake rtl2gds                   # sv2v + synthesis/place/route/GDS\nmake rtl2gds ORFS_TARGET=synth # stop after synthesis\n\n# Docker (ORFS image; used when host Yosys/OpenROAD is missing)\nORFS_TARGET=all PD_PLATFORM=ci-asap7 ./scripts/pd_docker.sh make rtl2gds\nmake decodes   # ensure decoder is up to date before synthesis\nmake soc       # ensure MMIO map + soc_defines.h match hw/soc/\n```\n\nFrom RTL simulation (see `work/<test>/stats.txt` after a run):\n\n| Benchmark | Instructions | Cycles | IPC | \n|---|---|---|---|\n| c.helloworld | 760 | 2293 | 0.3314 | \n| c.iaxpy | 109 | 235 | 0.4638 | \n| elf.dhrystone | 640720 | 1274337 | 0.5028 | \n\nOn Alveo U280 (100 MHz core, host-timed EOT) `elf.dhrystone` is ~12.9 ms for 2000 runs → ~155k dps / **~88.5 DMIPS** (~0.89 DMIPS/MHz). That matches the sim cycle count (1.274M cycles ≈ 12.7 ms at 100 MHz).\n\n| Submodule | Repository | Purpose | \n|---|---|---|\n| `SVLib` | [siliscale/SVLib](https://github.com/siliscale/SVLib) | Registers, program counter, arithmetic primitives | \n| `open-decode-tables` | [siliscale/open-decode-tables](https://github.com/siliscale/open-decode-tables) | YAML → SystemVerilog decode generator | \n\nAfter pulling submodule updates:\n\n```\ngit submodule update --init --recursive\nmake decodes\nmake soc\n```\n\nGitHub Actions runs on every push and pull request to `main`. The workflow (`.github/workflows/ci.yml`) mirrors a from-scratch developer setup:\n\n1. Checkout with submodules\n2. `make deps` — system packages, Python venv, RISC-V toolchain, Verilator,`scripts/env.sh`\n3. `make decodes` — regenerate the instruction decoder\n4. `make soc` — regenerate the MMIO map and`soc_defines.h`\n5. `make smoke-verilator` — full smoke regression (`tests/smoke.tlist` )\n\nNo Vivado license is required. `make deps` writes `scripts/env.sh`; subsequent `make` targets load it automatically — no manual `PATH` or `source venv/bin/activate` in CI.\n\nIf CI fails, check the job log for the failing test name, then reproduce locally with:\n\n```\nmake deps   # if not already done\n./scripts/with_env.sh ./tools/sim_manager.py -s verilator -n <test.name>\n```\n\nThis repository is developed and maintained by Siliscale. **We do not accept external contributions** — please do not open pull requests or submit patches.\n\nThe project is open source under the Apache License 2.0; you are free to use, study, and fork it for your own work. For collaboration, partnerships, or commercial engagement, see [Business inquiries](#business-inquiries).\n\nFor partnerships, consulting, custom accelerator work, or commercial licensing questions, contact **[marco@siliscale.com](mailto:marco@siliscale.com)**.\n\nApache License 2.0 — see [LICENSE](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/LICENSE).\n\n- [NOTICE](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/NOTICE) — attribution for this repo and bundled submodules\n- [THIRD_PARTY.md](https://github.com/spzbrnmrc/Tiny-Vedas/blob/main/THIRD_PARTY.md) — dev-only tools vs shipped components\n\nSPDX: `Apache-2.0`", "url": "https://wpnews.pro/news/tiny-vedas-a-generic-accelerator-interface-for-risc-v-from-pytorch-op-to-gds", "canonical_source": "https://github.com/spzbrnmrc/Tiny-Vedas", "published_at": "2026-09-18 17:11:27+00:00", "updated_at": "2026-09-18 17:25:29.027833+00:00", "lang": "en", "topics": ["ai-chips", "ai-infrastructure", "ai-research", "developer-tools", "machine-learning"], "entities": ["Tiny Vedas", "RISC-V", "PyTorch", "PyVedas", "OpenROAD", "SystemVerilog", "AXI4", "RV32IM"], "alternates": {"html": "https://wpnews.pro/news/tiny-vedas-a-generic-accelerator-interface-for-risc-v-from-pytorch-op-to-gds", "markdown": "https://wpnews.pro/news/tiny-vedas-a-generic-accelerator-interface-for-risc-v-from-pytorch-op-to-gds.md", "text": "https://wpnews.pro/news/tiny-vedas-a-generic-accelerator-interface-for-risc-v-from-pytorch-op-to-gds.txt", "jsonld": "https://wpnews.pro/news/tiny-vedas-a-generic-accelerator-interface-for-risc-v-from-pytorch-op-to-gds.jsonld"}}