rvgen ships with 27 built-in target configurations (the rv32i/rv32imc/
rv64gc/… targets from the riscv-dv target/ tree, plus a handful of
Zve* embedded-vector additions). For bringup of a custom core you
don't need to edit the framework — drop your configuration into the
user area and it's picked up automatically.
user/
├── README.md # top-level guide
├── targets/ # YAML target configs
│ ├── README.md # schema reference
│ └── chipforge-mcu.yaml # worked example
├── testlists/ # YAML testlists
│ └── README.md
├── streams/ # custom directed streams (Python)
│ └── README.md
└── coverage/ # CGF-format coverage-goal overlays
└── README.md
See user/README.md and each subdirectory's README.md for schemas
and examples.
Precedence (first match wins):
--user_dir <path>on the CLI.$RVGEN_USER_DIRenvironment variable../userrelative to the current working directory (only if it exists — so this default is harmless when unused).
Tip: if you want rvgen to operate on a user area outside the repo (e.g. in a private sibling checkout), point at it via the env var:
export RVGEN_USER_DIR=$HOME/my-chip-project/rvgen-site
python -m rvgen --target my_core --test riscv_rand_instr_test ...Three options, in decreasing order of rvgen-owned-ness:
- Write
user/targets/<your_core>.yamlfollowing the schema inuser/targets/README.md. python -m rvgen --target <your_core> ...— the name comes from your YAML'snamefield, not the filename.
The chipforge-mcu.yaml example shows a complete YAML with a
custom CLINT memory map, a restricted crypto ISA, and an
unsupported_instr denylist for SHA-512 split-pair opcodes the
physical core doesn't implement.
If you don't want to place the YAML in the user area:
python -m rvgen --target_config /any/path/to/my_core.yaml \
--test riscv_rand_instr_test ...Same schema as user/targets/*.yaml.
Only for targets upstreamed back to rvgen. Add a TargetCfg entry
to rvgen/targets/builtin.py and submit a PR.
python -m rvgen --help_targetsReports built-in targets and any user-area targets discoverable from the current user directory.
The four fields most likely to differ between your SoC and a generic riscv-dv target:
| Field | What it controls | Default |
|---|---|---|
clint.base |
Base address of the CLINT controller | 0x02000000 (SiFive CLINT / Spike / QEMU virt) |
clint.mtimecmp_offset |
MTIMECMP[0] = base + offset | 0x4000 |
clint.mtime_offset |
MTIME = base + offset | 0xBFF8 |
clint.msip_offset |
MSIP[0] = base + offset | 0x0 |
These land verbatim in the asm emitted by
rvgen.privileged.interrupts.gen_arm_timer_irq /
gen_clear_timer_irq / gen_arm_software_irq /
gen_clear_software_irq. If your SoC's timer is at a different
memory location, setting these is the difference between a test
that fires a real timer IRQ and a test that stores to random
addresses.
The SiFive CLINT layout works on Spike, QEMU virt, and most off-the-shelf RISC-V FPGA cores. Override only when you know your SoC differs.